簡明 Python 教程 Swaroop, C. H. 著 沈潔元 譯 www.byteofpython.info 版本:1.20 A Byte of Python Copyright □ 2003-2005 Swaroop C H 本書依照 創作公用約定(署名-非派生作品-非商業用途) 發布。 概要 無論您剛接觸電腦還是一個有經驗的程序員,本書都將有助您學習使用Python語言。 目錄表 前言 本書的讀者 本書的由來 本書目前的狀況 官方網站 約定條款 歡迎給我反饋 值得思考的一些東西 1. 介紹 簡介 Python的特色 概括 為什麼不使用Perl? 程序員的話 2. 安裝Python Linux和BSD用戶 Windows□用戶 概括 3. 最初的步驟 簡介 使用帶提示符的解釋器 挑選一個編輯器 使用源文件 輸出 它如何工作 可執行的Python程序 獲取幫助 概括 4. 基本概念 字面意義上的常量 數 字符串 變量 標識符的命名 數據類型 對象 輸出 它如何工作 邏輯行與物理行 縮進 概括 5. 運算符與表達式 簡介 運算符 運算符優先級 計算順序 結合規律 表達式 使用表達式 概括 6. 控制流 簡介 if語句 使用if語句 它如何工作 while語句 使用while語句 for循環 使用for語句 break語句 使用break語句 continue語句 使用continue語句 概括 7. 函數 簡介 定義函數 函數形參 使用函數形參 局部變量 使用局部變量 使用global語句 默認參數值 使用默認參數值 關鍵參數 使用關鍵參數 return語句 使用字面意義上的語句 DocStrings 使用DocStrings 概括 8. 模塊 簡介 使用sys模塊 字節編譯的.pyc文件 from..import語句 模塊的__name__ 使用模塊的__name__ 制造你自己的模塊 創建你自己的模塊 from..import dir()函數 使用dir函數 概括 9. 數據結構 簡介 列表 對象與類的快速入門 使用列表 元組 使用元組 元組與打印語句 字典 使用字典 序列 使用序列 參考 對象與參考 更多字符串的內容 字符串的方法 概括 10. 解決問題——編寫一個Python腳本 問題 解決方案 版本一 版本二 版本三 版本四 進一步優化 軟件開發過程 概括 11. 面向對象的編程 簡介 self 類 創建一個類 對象的方法 使用對象的方法 __init__方法 使用__init__方法 類與對象的變量 使用類與對象的變量 繼承 使用繼承 概括 12. 輸入/輸出 文件 使用文件 儲存器 儲存與取儲存 概括 13. 異常 錯誤 try..except 處理異常 引發異常 如何引發異常 try..finally 使用finally 概括 14. Python標准庫 簡介 sys模塊 命令行參數 更多sys的內容 os模塊 概括 15. 更多Python的內容 特殊的方法 單語句塊 列表綜合 使用列表綜合 在函數中接收元組和列表 lambda形式 使用lambda形式 exec和eval語句 assert語句 repr函數 概括 16. 接下來學習什麼? 圖形軟件 GUI工具概括 探索更多內容 概括 A. 自由/開放源碼軟件(FLOSS) B. 關于本書 后記 關于作者 關于譯者 關于簡體中文譯本 C. 修訂記錄 時間表 朮語表 表格 5.1 運算符與它們的用法 5.2 運算符優先級 15.1 一些特殊的方法 例子 3.1 使用帶提示符的Python解釋器 3.2 使用源文件 4.1 使用變量和字面意義上的常量 5.1 使用表達式 6.1 使用if語句 6.2 使用while語句 6.3 使用for語句 6.4 使用break語句 6.5 使用continue語句 7.1 定義函數 7.2 使用函數形參 7.3 使用局部變量 7.4 使用global語句 7.5 使用默認參數值 7.6 使用關鍵參數 7.7 使用字面意義上的語句 7.8 使用DocStrings 8.1 使用sys模塊 8.2 使用模塊的__name__ 8.3 如何創建你自己的模塊 8.4 使用dir函數 9.1 使用列表 9.2 使用元組 9.3 使用元組輸出 9.4 使用字典 9.5 使用序列 9.6 對象與參考 10.1 備份腳本——版本一 10.2 備份腳本——版本二 10.3 備份腳本——版本三(不工作!) 10.4 備份腳本——版本四 11.1 創建一個類 11.2 使用對象的方法 11.3 使用__init__方法 11.4 使用類與對象的變量 11.5 使用繼承 12.1 使用文件 12.2 儲存與取儲存 13.1 處理異常 13.2 如何引發異常 14.1 使用sys.argv 15.1 使用列表綜合 15.2 使用lambda形式 前言 目錄表 本書的讀者 本書的由來 本書目前的狀況 官方網站 約定條款 反饋 值得思考的一些東西 Python語言可能是第一種即簡單又功能強大的編程語言。它不僅適合于初學者,也適合于專業人 員使用,更加重要的是,用Python編程是一種愉快的事。本身將幫助你學習這個奇妙的語言,并 且向你展示如何即快捷又方便地完成任務——真正意義上“為編程問題提供的完美解決方案!” 本書的讀者 本書可以作為Python編程語言的一本指南或者教程。它主要是為新手而設計,不過對于有經驗的 程序員來說,它同樣有用。 即便你對計算機的了解只是如何在計算機上保存文本文件,你都可以通過本書學習Python。如果 你有編程經驗,你也可以使用本書學習Python。 如果你以前有編程經驗,那麼你將會對Python語言和其他你所鐘愛的編程語言之間的區別感興 趣。對此我為你指出了許多這樣的區別。順便提醒你,Python將很快成為你最喜歡的編程語言! 本書的由來 我最初接觸Python是當我需要為我的軟件鑽石寫一個方便安裝過程的安裝程序的時候。我得在 Python和Perl語言中選擇一個綁定Qt庫。我在網上做了一些研究,偶然發現了一篇文章。那是Eric S. Raymond(著名的電腦高手)談Python如何成為它最喜歡地編程語言的一篇文章。我同時發現 PyQt綁定與Perl-Qt相比要出色得多,所以我選擇了Python語言。 之后我開始尋找一本關于Python的優秀書籍。我竟然找不到!雖然我找到了一些O'Reilly的書,不 過它們不是太貴就是如同一本參考手冊而不是一本指南。我最后使用了Python附帶的文檔,不過 它太簡略了。那個文檔確實很好的給出了Python的概念,不過不夠全面。盡管最后我根據我以前 得編程經驗掌握了那個文檔,不過我覺得它完全不適合于新手。 大約在我首次使用Python語言的六個月之后,我安裝了那時最新的Red Hat 9.0 Linux。在我玩弄 KWord應用程序的時候,我突然想寫一點關于Python的東西。很快我就寫了30多頁,然后我開始 認真地想辦法把它變成一本完整的書。經過 多次 的改進和重寫,它終于成為了一本有用的完整 的Python語言學習指南。我把本書貢獻給開源軟件者們。 本書來自于我個人學習Python的筆記,不過我盡力讓它更加適合別人的口味。 在開源精神的鼓舞下,我收到了許多建設性的建議和批評以及來自熱心讀者的反饋,它們使這本 書變得更加出色。 本書目前的狀況 本書目前仍然在進一步完善中。許多章節已經頻繁地做了修改。然而本書已經十分成熟了,你一 定可以很容易地通過它學習Python。如果你覺得本書中有什麼錯誤或者難懂的地方,請告訴我。 本書將來計划增加更多的章節,包括wxPython,Twisted,有可能的話甚至還有Boa Constructor。 本書的官方網站是www.byteofpython.info。你可以在這個網站上在線閱讀本書,也可以下載本書的 最新版本或給我反饋。 約定條款 本書(原版)依照創作共用約定(署名-非商業作品-保持一致)發布。簡單地說,你只要署上我 的名字,就可以免費復制、分發和展示本書。未得到我的允許,你禁止把本書用于商業目的。你 在修改本書的時候,必須清楚地標明所有做了改動的地方,你發布修改后的作品時也必須遵照與 本書相同的約定。 請訪問創作公用約定的網站瀏覽約定全文,或者查看一個簡單易懂的約定描述。那里還有一個連 環畫似的約定條款的解釋。 反饋 我盡了很大的力讓這本書即生動又盡可能的准確。然而,如果你找到任何不太令你滿意的地方或 者錯誤,或者是需要改進的地方,請告訴我以便我改正它們。你可以把它們通過 swaroop@byteofpython.info發送給我。 值得思考的一些東西 有兩種方式構建軟件設計:一種是把軟件做得很簡單以至于明顯找不到缺陷﹔另一 種是把它做得很復雜以至于找不到明顯的缺陷。 ——C.A.R. Hoare 獲得人生中的成功需要的專注與堅持不懈多過天才與機會。 ——C.W. Wendte 第1章 介紹 目錄表 簡介 Python的特色 概括 為什麼不使用Perl? 程序員的話 簡介 Python語言是少有的一種可以稱得上即簡單又功能強大的編程語言。你將驚喜地發現Python語言 是多麼地簡單,它注重的是如何解決問題而不是編程語言的語法和結構。 Python的官方介紹是: Python是一種簡單易學,功能強大的編程語言,它有高效率的高層數據結構,簡單 而有效地實現面向對象編程。Python簡潔的語法和對動態輸入的支持,再加上解釋 性語言的本質,使得它在大多數平台上的許多領域都是一個理想的腳本語言,特別 適用于快速的應用程序開發。 我會在下一節里詳細地討論Python的這些特點。 注釋 Python語言的創造者Guido van Rossum是根據英國廣播公司的節目“蟒蛇飛行馬戲”命名這個語 言的,并非他本人特別喜歡蛇纏起它們的長身軀碾死動物覓食。 Python的特色 簡單 Python是一種代表簡單主義思想的語言。閱讀一個良好的Python程序就感覺像是在讀英語 一樣,盡管這個英語的要求非常嚴格!Python的這種偽代碼本質是它最大的優點之一。它 使你能夠專注于解決問題而不是去搞明白語言本身。 易學 就如同你即將看到的一樣,Python極其容易上手。前面已經提到了,Python有極其簡單的 語法。 免費、開源 Python是FLOSS(自由/開放源碼軟件)之一。簡單地說,你可以自由地發布這個軟件的拷 貝、閱讀它的源代碼、對它做改動、把它的一部分用于新的自由軟件中。FLOSS是基于一 個團體分享知識的概念。這是為什麼Python如此優秀的原因之一——它是由一群希望看到 一個更加優秀的Python的人創造并經常改進著的。 高層語言 當你用Python語言編寫程序的時候,你無需考慮諸如如何管理你的程序使用的內存一類的 底層細節。 可移植性 由于它的開源本質,Python已經被移植在許多平台上(經過改動使它能夠工作在不同平台 上)。如果你小心地避免使用依賴于系統的特性,那麼你的所有Python程序無需修改就可 以在下述任何平台上面運行。 這些平台包括Linux、Windows、FreeBSD、Macintosh、Solaris、OS/2、Amiga、AROS、 AS/400、BeOS、OS/390、z/OS、Palm OS、QNX、VMS、Psion、Acom RISC OS、 VxWorks、PlayStation、Sharp Zaurus、Windows CE甚至還有PocketPC! 解釋性 這一點需要一些解釋。 一個用編譯性語言比如C或C++寫的程序可以從源文件(即C或C++語言)轉換到一個你的 計算機使用的語言(二進制代碼,即0和1)。這個過程通過編譯器和不同的標記、選項完 成。當你運行你的程序的時候,連接/轉載器軟件把你的程序從硬盤復制到內存中并且運 行。 而Python語言寫的程序不需要編譯成二進制代碼。你可以直接從源代碼 運行 程序。在計算 機內部,Python解釋器把源代碼轉換成稱為字節碼的中間形式,然后再把它翻譯成計算機 使用的機器語言并運行。事實上,由于你不再需要擔心如何編譯程序,如何確保連接轉載 正確的庫等等,所有這一切使得使用Python更加簡單。由于你只需要把你的Python程序拷 貝到另外一台計算機上,它就可以工作了,這也使得你的Python程序更加易于移植。 面向對象 Python即支持面向過程的編程也支持面向對象的編程。在 面向過程 的語言中,程序是由過 程或僅僅是可重用代碼的函數構建起來的。在 面向對象 的語言中,程序是由數據和功能組 合而成的對象構建起來的。與其他主要的語言如C++和Java相比,Python以一種非常強大又 簡單的方式實現面向對象編程。 可擴展性 如果你需要你的一段關鍵代碼運行得更快或者希望某些算法不公開,你可以把你的部分程 序用C或C++編寫,然后在你的Python程序中使用它們。 可嵌入性 你可以把Python嵌入你的C/C++程序,從而向你的程序用戶提供腳本功能。 丰富的庫 Python標准庫確實很龐大。它可以幫助你處理各種工作,包括正則表達式、文檔生成、單 元測試、線程、數據庫、網頁瀏覽器、CGI、FTP、電子郵件、XML、XML-RPC、 HTML、WAV文件、密碼系統、GUI(圖形用戶界面)、Tk和其他與系統有關的操作。記 住,只要安裝了Python,所有這些功能都是可用的。這被稱作Python的“功能齊全”理 念。 除了標准庫以外,還有許多其他高質量的庫,如wxPython、Twisted和Python圖像庫等等。 概括 Python確實是一種十分精彩又強大的語言。它合理地結合了高性能與使得編寫程序簡單有趣的特 色。 為什麼不使用Perl? 也許你以前并不知道,Perl是另外一種極其流行的開源解釋性編程語言。 如果你曾經嘗試過用Perl語言編寫一個大程序,你一定會自己回答這個問題。在規模較小的時 候,Perl程序是簡單的。它可以勝任于小型的應用程序和腳本,“使工作完成”。然而,當你想 開始寫一些大一點的程序的時候,Perl程序就變得不實用了。我是通過為Yahoo編寫大型Perl程序 的經驗得出這樣的總結的! 與Perl相比,Python程序一定會更簡單、更清晰、更易于編寫,從而也更加易懂、易維護。我確 實也很喜歡Perl,用它來做一些日常的各種事情。不過當我要寫一個程序的時候,我總是想到使 用Python,這對我來說已經成了十分自然的事。Perl已經經歷了多次大的修正和改變,遺憾的 是,即將發布的Perl 6似乎仍然沒有在這個方面做什麼改進。 我感到Perl唯一也是十分重要的優勢是它龐大的CPAN庫——綜合Perl存檔網絡。就如同這個名字 所指的意思一樣,這是一個巨大的Perl模塊集,它大得讓人難以置信——你几乎用這些模塊在計 算機上做任何事情。Perl的模塊比Python多的原因之一是Perl擁有更加悠久的歷史。或許我會在 comp.lang.python上建議把Perl模塊移植到Python上的計划。 另外,新的Parrot虛擬機按設計可以運行完全重新設計的Perl 6也可以運行Python和其他解釋性語 言如Ruby、PHP和Tcl等等。這意味著你將來 或許 可以在Python上使用所有Perl的模塊。這將成為 兩全其美的事——強大的CPAN庫與強大的Python語言結合在一起。我們將拭目以待。 程序員的話 讀一下像ESR這樣的超級電腦高手談Python的話,你會感到十分有意思: ● Eric S. Raymond是《The Cathedral and the Bazaar》的作者、“開放源碼”一詞的提出人。他 說Python已經成為了他最喜愛的編程語言。這篇文章也是促使我第一次接觸Python的真正 原動力。 ● Bruce Eckel著名的《Thinking in Java》和《Thinking in C++》的作者。他說沒有一種語言比 得上Python使他的工作效率如此之高。同時他說Python可能是唯一一種旨在幫助程序員把 事情弄得更加簡單的語言。請閱讀完整的采訪以獲得更詳細的內容。 ● Peter Norvig是著名的Lisp語言書籍的作者和Google公司的搜索質量主任(感謝Guido van Rossum告訴我這一點)。他說Python始終是Google的主要部分。事實上你看一下Google招 聘的網頁就可以驗証這一點。在那個網頁上,Python知識是對軟件工程師的一個必需要 求。 ● Bruce Perens是OpenSource.org和UserLinux項目的一位共同創始人。UserLinux旨在創造一個 可以被多家發行商支持標准的Linux發行版。Python擊敗了其它競爭對手如Perl和Ruby成為 UserLinux支持的主要編程語言。 第2章 安裝Python 目錄表 Linux和BSD用戶 Windows□用戶 概括 Linux和BSD用戶 如果你正在使用一個Linux的發行版比如Fedora或者Mandrake或者其他(你的選擇),或者一個 BSD系統比如FreeBSD,那麼你可能已經在你的系統里安裝了Python。 要測試你是否已經隨著你的Linux包安裝了Python,你可以打開一個shell程序(就像konsole或 gnome-terminal)然后輸入如下所示的命令python -V。 $ python -V Python 2.3.4 注釋 $是shell的提示符。根據你的操作系統的設置,它可能與你那個不同,因此我只用$符號表示提示 符。 如果你看見向上面所示的那樣一些版本信息,那麼你已經安裝了Python了。 如果你得到像這樣的消息: $ python -V bash: python: command not found 那麼你還沒有安裝Python。這几乎不可能,只是極其偶爾才會遇到。 在這種情況下,你有兩種方法在你的系統上安裝Python。 ● 利用你的操作系統附帶的包管理軟件安裝二進制包,比如Fedora Linux的yum、Mandrake Linux的urpmi、Debian Linux的apt-get、FreeBSD的pkg_add等等。注意,使用這種方法的 話,你需要連接因特網。 你也可以從別的地方下載二進制包然后拷貝到你的PC中安裝。 ● 你可以從源代碼編譯Python然后安裝。在網站上有編譯的指令。 Windows□用戶 Windows□用戶可以訪問Python.org/download,從網站上下載最新的版本(在寫本書的時候,最新 版本是2.3.4版)。它的大小大約是9.4MB,與其他大多數語言相比是十分緊湊的。安裝過程與其 他Windows軟件類似。 提示 即便安裝程序為你提供了不檢查 可選 組件的選項,你也不要不作任何檢查!有些組件對你很有 用,特別是集成開發環境。 有趣的是,大約70%的Python下載是來自Windows用戶的。當然,這并不能說明問題,因為几乎 所有的Linux用戶已經在安裝系統的時候默認安裝了Python。 在Windows命令行中使用Python 如果你想要從Windows命令行調用Python,那麼你需要先正確的設置PATH變量。 對于Windows 2000、XP、2003,點擊控制面板->系統->高級->環境變量。在“系統變量”表單中 點擊叫做PATH的變量,然后編輯這個變量,把;C:\Python23加到它的結尾。當然,是Python所在 的正確目錄名。 對于較舊版本的Windows,把下面這行加到文件C:\AUTOEXEC.BAT中:PATH=%PATH%;C: \Python23,然后重新啟動系統。對于Windows NT,則使用AUTOEXEC.NT文件。 概括 對于Linux系統,很可能你已經在你的系統里安裝了Python。否則,你可以通過你的發行版附帶的 包管理軟件安裝Python。對于Windows系統,安裝Python就是下載安裝程序然后雙擊它那麼簡 單。從現在起,我們將假設你已經在你的系統里安裝了Python。 第3章 最初的步驟 目錄表 簡介 使用帶提示符的解釋器 挑選一個編輯器 使用源文件 輸出 它如何工作 可執行的Python程序 獲取幫助 概括 簡介 我們將看一下如何用Python編寫運行一個傳統的“Hello World”程序。通過它,你將學會如何編 寫、保存和運行Python程序。 有兩種使用Python運行你的程序的方式——使用交互式的帶提示符的解釋器或使用源文件。我們 將學習這兩種方法。 使用帶提示符的解釋器 在命令行的shell提示符下鍵入python,啟動解釋器。現在輸入print 'Hello World',然后按Enter鍵。 你應該可以看到輸出的單詞Hello World。 對于Windows用戶,只要你正確的設置了PATH變量,你應該可以從命令行啟動解釋器。或者你 可以選擇使用IDLE程序。IDLE是集成開發環境的縮寫。點擊開始->程序->Python 2.3->IDLE (Python GUI)。Linux用戶也可以使用IDLE。 注意,>>>是你鍵入Python語句的提示符。 例3.1 使用帶提示符的Python解釋器 $ python Python 2.3.4 (#1, Oct 26 2004, 16:42:40) [GCC 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> print 'hello world' hello world >>> 注意,Python會在下一行立即給出你輸出!你剛才鍵入的是一句Python 語句 。我們使用print(不 要驚訝)來打印你提供給它的值。這里,我們提供的是文本Hello World,它被迅速地打印在屏幕 上。 如何退出Python提示符 如果你使用的是Linux/BSD shell,那麼按Ctrl-d退出提示符。如果是在Windows命令行中,則按 Ctrl-z再按Enter。 挑選一個編輯器 在我們開始講述以源文件方式編寫Python程序之前,我們需要一個編輯器來寫源文件。挑選一個 編輯器確實是極其重要的。你挑選一個編輯器就如同你挑選一輛你將購買的轎車一樣。一個好的 編輯器會幫助你方便地編寫Python程序,使你地編程旅程更加舒適,幫助你更加快捷安全地到達 目的地(實現目標)。 對于編輯器的基本要求之一是語法加亮功能,利用這一功能,你的Python程序的不同部分被標以 不同的顏色,這樣你可以更好 看清楚 你的程序,使它的運行顯得形象化。 如果你使用Windows,那麼我建議你使用IDLE。IDLE具備語法加亮功能,還有許多其他的功能, 比如允許你在IDLE中運行你的程序。特別值得注意的是:不要使用Notepad——它是一個糟糕的 選擇,因為它沒有語法加亮功能,而且更加重要的是,它不支持文本縮進。而我們將會看到文本 縮進對于我們來說極其重要。一個好的編輯器,比如IDLE(還有VIM)將會自動幫助你做這些事 情。 如果你使用Linux/FreeBSD,那麼你有很多種選擇。如果你是一位有經驗的程序員,你一定已經在 使用VIM或者Emacs了。勿庸置疑,它們是兩個功能最強大的編輯器。使用它們編寫你的Python 程序,你將從中受益。我個人使用VIM編寫我的大多數程序。如果你是一個初學編程的人,那麼 你可以使用Kate,它也是我最喜歡的編輯器之一。只要你愿意花時間學習使用VIM或Emacs,那麼 我強烈建議你一定要學習兩者之一,因為從長遠看來它們對你是極其有幫助的。 如果你還想尋找一下其他可供選擇的編輯器,可以看一下詳盡的Python編輯器列表,然后作出你 的選擇。你也可以使用Python的IDE(集成開發環境)。請看一下詳盡的支持Python的IDE列表以 獲得詳盡的信息。一旦你開始編寫大型的Python程序,IDE確實很有用。 我再一次重申,請選擇一個合適的編輯器——它能使編寫Python程序變得更加有趣、方便。 使用源文件 現在讓我們重新開始編程。當你學習一種新的編程語言的時候,你編寫運行的第一個程序通常都 是“Hello World”程序,這已經成為一種傳統了。在你運行“Hello World”程序的時候,它所做 的事只是說聲:“Hello World”。正如提出“Hello World”程序的Simon Cozens[ ]所說:“它是 編程之神的傳統咒語,可以幫助你更好的學習語言。” 啟動你選擇的編輯器,輸入下面這段程序,然后把它保存為helloworld.py。 例3.2 使用源文件 #!/usr/bin/python # Filename : helloworld.py print 'Hello World' (源文件:code/helloworld.py) 為了運行這個程序,請打開shell(Linux終端或者DOS提示符),然后鍵入命令python helloworld. py。如果你使用IDLE,請使用菜單Edit->Run Script或者使用鍵盤快捷方式Ctrl-F5。輸出如下所 示。 輸出 $ python helloworld.py Hello World 如果你得到的輸出與上面所示的一樣,那麼恭喜!——你已經成功地運行了你的第一個Python程 序。 萬一你得到一個錯誤,那麼請確保你鍵入的程序 准確無誤 ,然后再運行一下程序。注意Python是 大小寫敏感的,即print與Print不一樣——注意前一個是小寫p而后一個是大寫P。另外,確保在每 一行的開始字符前沒有空格或者制表符——我們將在后面討論為什麼這點是重要的。 它如何工作 讓我們思考一下這個程序的前兩行。它們被稱作 注釋 ——任何在#符號右面的內容都是注釋。注 釋主要作為提供給程序讀者的筆記。 Python至少應當有第一行那樣的特殊形式的注釋。它被稱作 組織行 ——源文件的頭兩個字符是 #!,后面跟著一個程序。這行告訴你的Linux/Unix系統當你 執行 你的程序的時候,它應該運行哪 個解釋器。這會在下一節做詳細解釋。注意,你總是可以通過直接在命令行指定解釋器,從而在 任何平台上運行你的程序。就如同命令python helloworld.py一樣。 重要 在你的程序中合理地使用注釋以解釋一些重要的細節——這將有助于你的程序的讀者輕松地理解 程序在干什麼。記住,這個讀者可能就是6個月以后的你! 跟在注釋之后的是一句Python 語句 ——它只是打印文本“Hello World”。print實際上是一個操作 符,而“Hello World”被稱為一個字符串——別擔心我們會在后面詳細解釋這些朮語。 [1]一位最主要的Perl6/Parrot高手,轟動的《開始Perl》一書的作者。 可執行的Python程序 這部分內容只對Linux/Unix用戶適用,不過Windows用戶可能也對程序的第一行比較好奇。首先 我們需要通過chmod命令,給程序可執行的許可,然后 運行 程序。 $ chmod a+x helloworld.py $ ./helloworld.py Hello World chmod命令用來 改變 文件的 模式 ,給系統中所有用戶這個源文件的執行許可。然后我們可以直 接通過指定源文件的位置來執行程序。我們使用./來指示程序位于當前目錄。 為了更加有趣一些,你可以把你的文件名改成僅僅helloworld,然后運行./helloworld。這樣,這個 程序仍然可以工作,因為系統知道它必須用源文件第一行指定的那個解釋器來運行程序。 只要知道程序的確切位置,你現在就可以運行程序了——但是如果你希望你的程序能夠從各個位 置運行呢?那樣的話,你可以把你的程序保存在PATH環境變量中的目錄之一。每當你運行任何 程序,系統會查找列在PATH環境變量中的各個目錄。然后運行那個程序。你只要簡單地把這個 源文件復制到PATH所列目錄之一就可以使你的程序在任何位置都可用了。 $ echo $PATH /opt/mono/bin/:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/swaroop/bin $ cp helloworld.py /home/swaroop/bin/helloworld $ helloworld Hello World 我們能夠用echo命令來顯示PATH變量,用$給變量名加前綴以向shell表示我們需要這個變量的 值。我們看到/home/swaroop/bin是PATH變量中的目錄之一。swaroop是我的系統中使用的用戶 名。通常,在你的系統中也會有一個相似的目錄。你也可以把你選擇的目錄添加到PATH變量中 去——這可以通過運行PATH=$PATH:/home/swaroop/mydir完成,其中“/home/swaroop/ mydir”是我想要添加到PATH變量中的目錄。 當你想要在任何時間、任何地方運行你的程序的時候,這個方法十分有用。它就好像創造你自己 的指令,如同cd或其他Linux終端或DOS提示符命令那樣。 提示 對于Python來說,程序、腳本或者軟件都是指同一個東西。 獲取幫助 如果你需要某個Python函數或語句的快速信息幫助,那麼你可以使用內建的help功能。尤其在你 使用帶提示符的命令行的時候,它十分有用。比如,運行help(str)——這會顯示str類的幫助。str 類用于保存你的程序使用的各種文本(字符串)。類將在后面面向對象編程的章節詳細解釋。 注釋 按q退出幫助。 類似地,你可以獲取Python中几乎所有東西的信息。使用help()去學習更多關于help本身的東西! 如果你想要獲取關于如print那樣操作符的幫助,那麼你需要正確的設置PYTHONDOCS環境變 量。這可以在Linux/Unix中輕松地通過env命令完成。 $ env PYTHONDOCS=/usr/share/doc/python-docs-2.3.4/html/ python Python 2.3.4 (#1, Oct 26 2004, 16:42:40) [GCC 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> help('print') 你應該注意到我特意在“print”上使用了引號,那樣Python就可以理解我是希望獲取關 于“print”的幫助而不是想要它打印東西。 注意,我使用的位置是在Fedora Core 3 Linux中的位置——它可能在不同的發行版和版本中有所不 同。 概括 你現在應該可以方便地編寫、保存和運行Python程序了。既然你是一個Python用戶,讓我們學習 更多Python的概念。 第4章 基本概念 目錄表 字面意義上的常量 數 字符串 變量 標識符的命名 數據類型 對象 輸出 它如何工作 邏輯行與物理行 縮進 概括 僅僅打印“Hello World”就足夠了嗎?你應該想要做更多的事——你想要得到一些輸入,然后做 操作,再從中得到一些輸出。在Python中,我們可以使用常量和變量來完成這些工作。 字面意義上的常量 一個字面意義上的常量的例子是如同5、1.23、9.25e-3這樣的數,或者如同'This is a string'、"It's a string!"這樣的字符串。它們被稱作字面意義上的,因為它們具備 字面 的意義——你按照它們的字 面意義使用它們的值。數2總是代表它自己,而不會是別的什麼東西——它是一個常量,因為不 能改變它的值。因此,所有這些都被稱為字面意義上的常量。 數 在Python中有4種類型的數——整數、長整數、浮點數和復數。 ● 2是一個整數的例子。 ● 長整數不過是大一些的整數。 ● 3.23和52.3E-4是浮點數的例子。E標記表示10的冪。在這里,52.3E-4表示52.3 * 10-4。 ● (-5+4j)和(2.3-4.6j)是復數的例子。 字符串 字符串是 字符的序列 。字符串基本上就是一組單詞。 我几乎可以保証你在每個Python程序中都要用到字符串,所以請特別留心下面這部分的內容。下 面告訴你如何在Python中使用字符串。 ● 使用單引號(') 你可以用單引號指示字符串,就如同'Quote me on this'這樣。所有的空白,即空格和制表符 都照原樣保留。 ● 使用雙引號(") 在雙引號中的字符串與單引號中的字符串的使用完全相同,例如"What's your name?"。 ● 使用三引號('''或""") 利用三引號,你可以指示一個多行的字符串。你可以在三引號中自由的使用單引號和雙引 號。例如: '''This is a multi-line string. This is the first line. This is the second line. "What's your name?," I asked. He said "Bond, James Bond." ''' ● 轉義符 假設你想要在一個字符串中包含一個單引號('),那麼你該怎麼指示這個字符串?例如, 這個字符串是What's your name?。你肯定不會用'What's your name?'來指示它,因為Python會 弄不明白這個字符串從何處開始,何處結束。所以,你需要指明單引號而不是字符串的結 尾。可以通過 轉義符 來完成這個任務。你用\'來指示單引號——注意這個反斜杠。現在你 可以把字符串表示為'What\'s your name?'。 另一個表示這個特別的字符串的方法是"What's your name?",即用雙引號。類似地,要在雙 引號字符串中使用雙引號本身的時候,也可以借助于轉義符。另外,你可以用轉義符\\來 指示反斜杠本身。 值得注意的一件事是,在一個字符串中,行末的單獨一個反斜杠表示字符串在下一行繼 續,而不是開始一個新的行。例如: "This is the first sentence.\ This is the second sentence." 等價于"This is the first sentence. This is the second sentence." ● 自然字符串 如果你想要指示某些不需要如轉義符那樣的特別處理的字符串,那麼你需要指定一個自然 字符串。自然字符串通過給字符串加上前綴r或R來指定。例如r"Newlines are indicated by \n"。 ● Unicode字符串 Unicode是書寫國際文本的標准方法。如果你想要用你的母語如北印度語或阿拉伯語寫文 本,那麼你需要有一個支持Unicode的編輯器。類似地,Python允許你處理Unicode文本 ——你只需要在字符串前加上前綴u或U。例如,u"This is a Unicode string."。 記住,在你處理文本文件的時候使用Unicode字符串,特別是當你知道這個文件含有用非英 語的語言寫的文本。 ● 字符串是不可變的 這意味著一旦你創造了一個字符串,你就不能再改變它了。雖然這看起來像是一件壞事, 但實際上它不是。我們將會在后面的程序中看到為什麼我們說它不是一個缺點。 ● 按字面意義級連字符串 如果你把兩個字符串按字面意義相鄰放著,他們會被Python自動級連。例如,'What\'s' 'your name?'會被自動轉為"What's your name?"。 給C/C++程序員的注釋 在Python中沒有專門的char數據類型。確實沒有需要有這個類型,我相信你不會為此而煩惱。 給Perl/PHP程序員的注釋 記住,單引號和雙引號字符串是完全相同的——它們沒有在任何方面有不同。 給正則表達式用戶的注釋 一定要用自然字符串處理正則表達式。否則會需要使用很多的反斜杠。例如,后向引用符可以寫 成'\\1'或r'\1'。 變量 僅僅使用字面意義上的常量很快就會引發煩惱——我們需要一種既可以儲存信息 又可以對它們進 行操作的方法。這是為什麼要引入 變量 。變量就是我們想要的東西——它們的值可以變化,即 你可以使用變量存儲任何東西。變量只是你的計算機中存儲信息的一部分內存。與字面意義上的 常量不同,你需要一些能夠訪問這些變量的方法,因此你給變量名字。 標識符的命名 變量是標識符的例子。 標識符 是用來標識 某樣東西 的名字。在命名標識符的時候,你要遵循這 些規則: ● 標識符的第一個字符必須是字母表中的字母(大寫或小寫)或者一個下划線(‘ _ ’)。 ● 標識符名稱的其他部分可以由字母(大寫或小寫)、下划線(‘ _ ’)或數字(0-9)組 成。 ● 標識符名稱是對大小寫敏感的。例如,myname和myName不是一個標識符。注意前者中的 小寫n和后者中的大寫N。 ● 有效 標識符名稱的例子有i、__my_name、name_23和a1b2_c3。 ● 無效 標識符名稱的例子有2things、this is spaced out和my-name。 數據類型 變量可以處理不同類型的值,稱為數據類型。基本的類型是數和字符串,我們已經討論過它們 了。在后面的章節里面,我們會研究怎麼用類創造我們自己的類型。 對象 記住,Python把在程序中用到的任何東西都稱為 對象 。這是從廣義上說的。因此我們不會說“某 某 東西 ”,我們說“某個 對象 ”。 給面向對象編程用戶的注釋 就每一個東西包括數、字符串甚至函數都是對象這一點來說,Python是極其完全地面向對象的。 我們將看一下如何使用變量和字面意義上的常量。保存下面這個例子,然后運行程序。 如何編寫Python程序 下面是保存和運行Python程序的標准流程。 1. 打開你最喜歡的編輯器。 2. 輸入例子中的程序代碼。 3. 用注釋中給出的文件名把它保存為一個文件。我按照慣例把所有的Python程序都以擴展名.py 保存。 4. 運行解釋器命令python program.py或者使用IDLE運行程序。你也可以使用先前介紹的可執行 的方法。 例4.1 使用變量和字面意義上的常量 # Filename : var.py i=5 print i i=i+1 print i s = '''This is a multi-line string. This is the second line.''' print s (源文件:code/var.py) 輸出 $ python var.py 5 6 This is a multi-line string. This is the second line. 它如何工作 下面來說明一下這個程序如何工作。首先我們使用賦值運算符(=)把一個字面意義上的常數5賦 給變量i。這一行稱為一個語句。語句聲明需要做某件事情,在這個地方我們把變量名i與值5連接 在一起。接下來,我們用print語句打印i的值,就是把變量的值打印在屏幕上。 然后我們對i中存儲的值加1,再把它存回i。我們打印它時,得到期望的值6。 類似地,我們把一個字面意義上的字符串賦給變量s然后打印它。 給C/C++程序員的注釋 使用變量時只需要給它們賦一個值。不需要聲明或定義數據類型。 邏輯行與物理行 物理行是你在編寫程序時所 看見 的。邏輯行是Python 看見 的單個語句。Python假定每個 物理行 對應一個 邏輯行 。 邏輯行的例子如print 'Hello World'這樣的語句——如果它本身就是一行(就像你在編輯器中看到 的那樣),那麼它也是一個物理行。 默認地,Python希望每行都只使用一個語句,這樣使得代碼更加易讀。 如果你想要在一個物理行中使用多于一個邏輯行,那麼你需要使用分號(;)來特別地標明這種用 法。分號表示一個邏輯行/語句的結束。例如: i=5 print i 與下面這個相同: i = 5; print i; 同樣也可以寫成: i = 5; print i; 甚至可以寫成: i = 5; print i 然而,我強烈建議你堅持在每個物理行只寫一句邏輯行。僅僅當邏輯行太長的時候,在多于一個 物理行寫一個邏輯行。這些都是為了盡可能避免使用分號,從而讓代碼更加易讀。事實上,我 從 來沒有 在Python程序中使用過或看到過分號。 下面是一個在多個物理行中寫一個邏輯行的例子。它被稱為明確的行連接。 s = 'This is a string. \ This continues the string.' print s 它的輸出: This is a string. This continues the string. 類似地, print \ i 與如下寫法效果相同: print i 有時候,有一種暗示的假設,可以使你不需要使用反斜杠。這種情況出現在邏輯行中使用了圓括 號、方括號或波形括號的時候。這被稱為暗示的行連接。你會在后面介紹如何使用列表的章節中 看到這種用法。 縮進 空白在Python中是重要的。事實上行首的空白是重要的。它稱為縮進。在邏輯行首的空白(空格 和制表符)用來決定邏輯行的縮進層次,從而用來決定語句的分組。 這意味著同一層次的語句必須有相同的縮進。每一組這樣的語句稱為一個塊。我們將在后面的章 節中看到有關塊的用處的例子。 你需要記住的一樣東西是錯誤的縮進會引發錯誤。例如: i=5 print 'Value is', i # Error! Notice a single space at the start of the line print 'I repeat, the value is', i 當你運行這個程序的時候,你會得到下面的錯誤: File "whitespace.py", line 4 print 'Value is', i # Error! Notice a single space at the start of the line ^ SyntaxError: invalid syntax 注意,在第二行的行首有一個空格。Python指示的這個錯誤告訴我們程序的語法是無效的,即程 序沒有正確地編寫。它告訴你, 你不能隨意地開始新的語句塊 (當然除了你一直在使用的主 塊)。何時你能夠使用新塊,將會在后面的章節,如控制流中詳細介紹。 如何縮進 不要混合使用制表符和空格來縮進,因為這在跨越不同的平台的時候,無法正常工作。我 強烈建 議 你在每個縮進層次使用 單個制表符 或 兩個或四個空格 。 選擇這三種縮進風格之一。更加重要的是,選擇一種風格,然后一貫地使用它,即 只 使用這一 種風格。 概括 現在我們已經學習了很多詳細的內容,我們可以開始學習更加令你感興趣的東西,比如控制流語 句。在繼續學習之前,請確信你對本章的內容清楚明了。 第5章 運算符與表達式 目錄表 簡介 運算符 運算符優先級 計算順序 結合規律 表達式 使用表達式 概括 簡介 你編寫的大多數語句(邏輯行)都包含表達式。一個簡單的表達式例子如2 + 3。一個表達式可以 分解為運算符和操作數。 運算符 的功能是完成某件事,它們由如+這樣的符號或者其他特定的關鍵字表示。運算符需要數 據來進行運算,這樣的數據被稱為 操作數 。在這個例子中,2和3是操作數。 運算符 我們將簡單瀏覽一下運算符和它們的用法: 技巧 你可以交互地使用解釋器來計算例子中給出的表達式。例如,為了測試表達式2 + 3,使用 交互式的帶提示符的Python解釋器: >>> 2 + 3 5 >>> 3 * 5 15 >>> 表5.1 運算符與它們的用法 運算符 名稱 說明 例子 + 加 兩個對象相加 3 + 5得到8。'a' + 'b'得到'ab'。 - 減 得到負數或是一個數減去另一個數 -5.2得到一個負數。50 - 24得到26。 * 乘 兩個數相乘或是返回一個被重復若干次的字符串 2 * 3得到6。'la' * 3得到'lalala'。 ** 冪 返回x的y次冪 3 ** 4得到81(即3 * 3 * 3 * 3) / 除 x除以y 4/3得到1(整數的除法得到整數結果)。4.0/3或4/3.0得到 1.3333333333333333 // 取整除 返回商的整數部分 4 // 3.0得到1.0 % 取模 返回除法的余數 8%3得到2。-25.5%2.25得到1.5 << 左移 把一個數的比特向左移一定數目(每個數在內存中都表示為比特或二進制數字,即0和1) 2 << 2得到8。——2按比特表示為10 >> 右移 把一個數的比特向右移一定數目 11 >> 1得到5。——11按比特表示為 1011,向右移動1比特后得到101,即十進制的5。 & 按位與 數的按位與 5 & 3得到1。 | 按位或 數的按位或 5 | 3得到7。 ^ 按位異或 數的按位異或 5 ^ 3得到6 ~ 按位翻轉 x的按位翻轉是-(x+1) ~5得到6。 < 小于 返回x是否小于y。所有比較運算符返回1表示真,返回0表示假。這分別與特殊的變量True和False等價。注意,這些變量名的大寫。5 < 3返回0(即False)而3 < 5返回1(即 True)。比較可以被任意連接:3 < 5 < 7 返回True。 > 大于 返回x是否大于y 5 > 3返回True。如果兩個操作數都是數字,它們首先被轉換為一個共同的類型。否則,它總是返回False。 <= 小于等于 返回x是否小于等于y x = 3; y = 6; x <= y返回True。 >= 大于等于 返回x是否大于等于y x = 4; y = 3; x >= y返回True。 == 等于 比較對象是否相等 x = 2; y = 2; x == y返回True。x = 'str'; y = 'stR'; x == y返回False。x = 'str'; y = 'str'; x == y返回True。 != 不等于 比較兩個對象是否不相等 x = 2; y = 3; x != y返回True。 not 布爾“非” 如果x為True,返回False。如果x為False,它返回True。 x = True; not y返回False。 and 布爾“與” 如果x為False,x and y返回False,x = False; y = True; x and y,由于x是 False,返回False。在這里,Python不會計算y,因為它知道這個表達式的值肯定是False(因為x是False)。這個現象稱為短路計算。否則它返回y的計算值。 or 布爾“或” 如果x是True,它返回True,否則它返回y的計算值。x = True; y = False; x or y返回True。短路計算在這里也適用。 運算符優先級 如果你有一個如2 + 3 * 4那樣的表達式,是先做加法呢,還是先做乘法?我們的中學數學告訴我們 應當先做乘法——這意味著乘法運算符的優先級高于加法運算符。 下面這個表給出Python的運算符優先級,從最低的優先級(最松散地結合)到最高的優先級(最 緊密地結合)。這意味著在一個表達式中,Python會首先計算表中較下面的運算符,然后在計算 列在表上部的運算符。 下面這張表(與Python參考手冊中的那個表一模一樣)已經顧及了完整的需要。事實上,我建議 你使用圓括號來分組運算符和操作數,以便能夠明確地指出運算的先后順序,使程序盡可能地易 讀。例如,2 + (3 * 4)顯然比2 + 3 * 4清晰。與此同時,圓括號也應該正確使用,而不應該用得過濫 (比如2 + (3 + 4))。 表5.2 運算符優先級 運算符 描述 lambda Lambda表達式 or 布爾“或” and 布爾“與” not x 布爾“非” in,not in 成員測試 is,is not 同一性測試 <,<=,>,>=,!=,== 比較 | 按位或 ^ 按位異或 & 按位與 <<,>> 移位 +,- 加法與減法 *,/,% 余 +x,-x 正負號 ~x 按位翻轉 ** 指數 x.attribute 屬性參考 x[index] 下標 x[index:index] 尋址段 f(arguments...) 函數調用 (experession,...) 綁定或元組顯示 [expression,...] 列表顯示 {key:datum,...} 字典顯示 'expression,...' 字符串轉換 其中我們還沒有接觸過的運算符將在后面的章節中介紹。 在表中列在同一行的運算符具有 相同優先級 。例如,+和-有相同的優先級。 計算順序 默認地,運算符優先級表決定了哪個運算符在別的運算符之前計算。然而,如果你想要改變它們 的計算順序,你得使用圓括號。例如,你想要在一個表達式中讓加法在乘法之前計算,那麼你就 得寫成類似(2 + 3) * 4的樣子。 結合規律 運算符通常由左向右結合,即具有相同優先級的運算符按照從左向右的順序計算。例如,2 + 3 + 4被計算成(2 + 3) + 4。一些如賦值運算符那樣的運算符是由右向左結合的,即a = b = c被處理為a = (b = c)。 表達式 使用表達式 例5.1 使用表達式 #!/usr/bin/python # Filename: expression.py length = 5 breadth = 2 area = length * breadth print 'Area is', area print 'Perimeter is', 2 * (length + breadth) (源文件:code/expression.py) 輸出 $ python expression.py Area is 10 Perimeter is 14 它如何工作 矩形的長度與寬度存儲在以它們命名的變量中。我們借助表達式使用它們計算矩形的面積和邊 長。我們表達式length * breadth的結果存儲在變量area中,然后用print語句打印。在另一個打印語 句中,我們直接使用表達式2 * (length + breadth)的值。 另外,注意Python如何打印“漂亮的”輸出。盡管我們沒有在'Area is'和變量area之間指定空格, Python自動在那里放了一個空格,這樣我們就可以得到一個清晰漂亮的輸出,而程序也變得更加 易讀(因為我們不需要擔心輸出之間的空格問題)。這是Python如何使程序員的生活變得更加輕 松的一個例子。 概括 我們已經學習了如何使用運算符、操作數和表達式——這些使任何程序的基本組成部分。接下 來,我們將學習如何通過語句在我們的程序中使用這些部分。 第6章 控制流 目錄表 簡介 if語句 使用if語句 它如何工作 while語句 使用while語句 for循環 使用for語句 break語句 使用break語句 continue語句 使用continue語句 概括 簡介 在到目前為止我們所見到的程序中,總是有一系列的語句,Python忠實地按照它們的順序執行它 們。如果你想要改變語句流的執行順序,該怎麼辦呢?例如,你想要讓程序做一些決定,根據不 同的情況做不同的事情,例如根據時間打印“早上好”或者“晚上好”。 你可能已經猜到了,這是通過控制流語句實現的。在Python中有三種控制流語句——if、for和 while。 if語句 if語句用來檢驗一個條件, 如果 條件為真,我們運行一塊語句(稱為 if-塊 ), 否則 我們處理另 外一塊語句(稱為 else-塊 )。 else 從句是可選的。 使用if語句 例6.1 使用if語句 #!/usr/bin/python # Filename: if.py number = 23 guess = int(raw_input('Enter an integer : ')) if guess == number: print 'Congratulations, you guessed it.' # New block starts here print "(but you do not win any prizes!)" # New block ends here elif guess < number: print 'No, it is a little higher than that' # Another block # You can do whatever you want in a block ... else: print 'No, it is a little lower than that' # you must have guess > number to reach here print 'Done' # This last statement is always executed, after the if statement is executed (源文件:code/if.py) 輸出 $ python if.py Enter an integer : 50 No, it is a little lower than that Done $ python if.py Enter an integer : 22 No, it is a little higher than that Done $ python if.py Enter an integer : 23 Congratulations, you guessed it. (but you do not win any prizes!) Done 它如何工作 在這個程序中,我們從用戶處得到猜測的數,然后檢驗這個數是否是我們手中的那個。我們把變 量number設置為我們想要的任何整數,在這個例子中是23。然后,我們使用raw_input()函數取得 用戶猜測的數字。函數只是重用的程序段。我們將在下一章學習更多關于函數的知識。 我們為內建的raw_input函數提供一個字符串,這個字符串被打印在屏幕上,然后等待用戶的輸 入。一旦我們輸入一些東西,然后按回車鍵之后,函數返回輸入。對于raw_input函數來說是一個 字符串。我們通過int把這個字符串轉換為整數,并把它存儲在變量guess中。事實上,int是一個 類,不過你想在對它所需了解的只是它把一個字符串轉換為一個整數(假設這個字符串含有一個 有效的整數文本信息)。 接下來,我們將用戶的猜測與我們選擇的數做比較。如果他們相等,我們打印一個成功的消息。 注意我們使用了縮進層次來告訴Python每個語句分別屬于哪一個塊。這就是為什麼縮進在Python 如此重要的原因。我希望你能夠堅持“每個縮進層一個制表符”的規則。你是這樣的嗎? 注意if語句在結尾處包含一個冒號——我們通過它告訴Python下面跟著一個語句塊。 然后,我們檢驗猜測是否小于我們的數,如果是這樣的,我們告訴用戶它的猜測大了一點。我們 在這里使用的是elif從句,它事實上把兩個相關聯的if else-if else語句合并為一個if-elif-else語句。這 使得程序更加簡單,并且減少了所需的縮進數量。 elif和else從句都必須在邏輯行結尾處有一個冒號,下面跟著一個相應的語句塊(當然還包括正確 的縮進)。 你也可以在一個if塊中使用另外一個if語句,等等——這被稱為嵌套的if語句。 記住,elif和else部分是可選的。一個最簡單的有效if語句是: if True: print 'Yes, it is true' 在Python執行完一個完整的if語句以及與它相關聯的elif和else從句之后,它移向if語句塊的下一個 語句。在這個例子中,這個語句塊是主塊。程序從主塊開始執行,而下一個語句是print 'Done'語 句。在這之后,Python看到程序的結尾,簡單的結束運行。 盡管這是一個非常簡單的程序,但是我已經在這個簡單的程序中指出了許多你應該注意的地方。 所有這些都是十分直接了當的(對于那些擁有C/C++背景的用戶來說是尤為簡單的)。它們在開 始時會引起你的注意,但是以后你會對它們感到熟悉、“自然”。 給C/C++程序員的注釋 在Python中沒有switch語句。你可以使用if..elif..else語句來完成同樣的工作(在某些場合,使用字 典會更加快捷。) while語句 只要在一個條件為真的情況下,while語句允許你重復執行一塊語句。while語句是所謂 循環 語句 的一個例子。while語句有一個可選的else從句。 使用while語句 例6.2 使用while語句 #!/usr/bin/python # Filename: while.py number = 23 running = True while running: guess = int(raw_input('Enter an integer : ')) if guess == number: print 'Congratulations, you guessed it.' running = False # this causes the while loop to stop elif guess < number: print 'No, it is a little higher than that' else: print 'No, it is a little lower than that' else: print 'The while loop is over.' # Do anything else you want to do here print 'Done' (源文件:code/while.py) 輸出 $ python while.py Enter an integer : 50 No, it is a little lower than that. Enter an integer : 22 No, it is a little higher than that. Enter an integer : 23 Congratulations, you guessed it. The while loop is over. Done 它如何工作 在這個程序中,我們仍然使用了猜數游戲作為例子,但是這個例子的優勢在于用戶可以不斷的猜 數,直到他猜對為止——這樣就不需要像前面那個例子那樣為每次猜測重復執行一遍程序。這個 例子恰當地說明了while語句的使用。 我們把raw_input和if語句移到了while循環內,并且在while循環開始前把running變量設置為True。 首先,我們檢驗變量running是否為True,然后執行后面的 while-塊 。在執行了這塊程序之后,再 次檢驗條件,在這個例子中,條件是running變量。如果它是真的,我們再次執行while-塊,否 則,我們繼續執行可選的else-塊,并接著執行下一個語句。 當while循環條件變為False的時候,else塊才被執行——這甚至也可能是在條件第一次被檢驗的時 候。如果while循環有一個else從句,它將始終被執行,除非你的while循環將永遠循環下去不會結 束! True和False被稱為布爾類型。你可以分別把它們等效地理解為值1和0。在檢驗重要條件的時候, 布爾類型十分重要,它們并不是真實的值1。 else塊事實上是多余的,因為你可以把其中的語句放在同一塊(與while相同)中,跟在while語句 之后,這樣可以取得相同的效果。 給C/C++程序員的注釋 記住,你可以在while循環中使用一個else從句。 for循環 for..in是另外一個循環語句,它在一序列的對象上 遞歸 即逐一使用隊列中的每個項目。我們會在 后面的章節中更加詳細地學習序列。 使用for語句 例6.3 使用for語句 #!/usr/bin/python # Filename: for.py for i in range(1, 5): print i else: print 'The for loop is over' 輸出 $ python for.py 1 2 3 4 The for loop is over 它如何工作 在這個程序中,我們打印了一個 序列 的數。我們使用內建的range函數生成這個數的序列。 我們所做的只是提供兩個數,range返回一個序列的數。這個序列從第一個數開始到第二個數為 止。例如,range(1,5)給出序列[1, 2, 3, 4]。默認地,range的步長為1。如果我們為range提供第三個 數,那麼它將成為步長。例如,range(1,5,2)給出[1,3]。記住,range 向上 延伸到第二個數,即它不 包含第二個數。 for循環在這個范圍內遞歸——for i in range(1,5)等價于for i in [1, 2, 3, 4],這就如同把序列中的每個 數(或對象)賦值給i,一次一個,然后以每個i的值執行這個程序塊。在這個例子中,我們只是 打印i的值。 記住,else部分是可選的。如果包含else,它總是在for循環結束后執行一次,除非遇到break語句。 記住,for..in循環對于任何序列都適用。這里我們使用的是一個由內建range函數生成的數的列 表,但是廣義說來我們可以使用任何種類的由任何對象組成的序列!我們會在后面的章節中詳細 探索這個觀點。 給C/C++/Java/C#程序員的注釋 Python的for循環從根本上不同于C/C++的for循環。C#程序員會注意到Python的for循環與C#中的 foreach循環十分類似。Java程序員會注意到它與Java 1.5中的for (int i : IntArray)相似。 在C/C++中,如果你想要寫for (int i = 0; i < 5; i++),那麼用Python,你寫成for i in range(0,5)。你會 注意到,Python的for循環更加簡單、明白、不易出錯。 break語句 break語句是用來 終止 循環語句的,即哪怕循環條件沒有稱為False或序列還沒有被完全遞歸,也 停止執行循環語句。 一個重要的注釋是,如果你從for或while循環中 終止 ,任何對應的循環else塊將不執行。 使用break語句 例6.4 使用break語句 #!/usr/bin/python # Filename: break.py while True: s = raw_input('Enter something : ') if s == 'quit': break print 'Length of the string is', len(s) print 'Done' (源文件:code/break.py) 輸出 $ python break.py Enter something : Programming is fun Length of the string is 18 Enter something : When the work is done Length of the string is 21 Enter something : if you wanna make your work also fun: Length of the string is 37 Enter something : use Python! Length of the string is 12 Enter something : quit Done 它如何工作 在這個程序中,我們反復地取得用戶地輸入,然后打印每次輸入地長度。我們提供了一個特別的 條件來停止程序,即檢驗用戶的輸入是否是'quit'。通過 終止 循環到達程序結尾來停止程序。 輸入字符串的長度通過內建的len函數取得。 記住,break語句也可以在for循環中使用。 G2的Python詩 我在這里輸入的是我所寫的一段小詩,稱為G2的Python詩: Programming is fun When the work is done if you wanna make your work also fun: use Python! continue語句 continue語句被用來告訴Python跳過當前循環塊中的剩余語句,然后 繼續 進行下一輪循環。 使用continue語句 例6.5 使用continue語句 #!/usr/bin/python # Filename: continue.py while True: s = raw_input('Enter something : ') if s == 'quit': break if len(s) < 3: continue print 'Input is of sufficient length' # Do other kinds of processing here... (源文件:code/continue.py) 輸出 $ python continue.py Enter something : a Enter something : 12 Enter something : abc Input is of sufficient length Enter something : quit 它如何工作 在這個程序中,我們從用戶處取得輸入,但是我們僅僅當它們有至少3個字符長的時候才處理它 們。所以,我們使用內建的len函數來取得長度。如果長度小于3,我們將使用continue語句忽略塊 中的剩余的語句。否則,這個循環中的剩余語句將被執行,我們可以在這里做我們希望的任何處 理。 注意,continue語句對于for循環也有效。 概括 我們已經學習了如何使用三種控制流語句——if、while和for以及與它們相關的break和continue語 句。它們是Python中最常用的部分,熟悉這些控制流是應當掌握的基本技能。 接下來,我們將學習如何創建和使用函數。 第7章 函數 目錄表 簡介 定義函數 函數形參 使用函數形參 局部變量 使用局部變量 使用global語句 默認參數值 使用默認參數值 關鍵參數 使用關鍵參數 return語句 使用字面意義上的語句 DocStrings 使用DocStrings 概括 簡介 函數是重用的程序段。它們允許你給一塊語句一個名稱,然后你可以在你的程序的任何地方使用 這個名稱任意多次地運行這個語句塊。這被稱為 調用 函數。我們已經使用了許多內建的函數, 比如len和range。 函數通過def關鍵字定義。def關鍵字后跟一個函數的 標識符 名稱,然后跟一對圓括號。圓括號之 中可以包括一些變量名,該行以冒號結尾。接下來是一塊語句,它們是函數體。下面這個例子將 說明這事實上是十分簡單的: 定義函數 例7.1 定義函數 #!/usr/bin/python # Filename: function1.py def sayHello(): print 'Hello World!' # block belonging to the function sayHello() # call the function (源文件:code/function1.py) 輸出 $ python function1.py Hello World! 它如何工作 我們使用上面解釋的語法定義了一個稱為sayHello的函數。這個函數不使用任何參數,因此在圓 括號中沒有聲明任何變量。參數對于函數而言,只是給函數的輸入,以便于我們可以傳遞不同的 值給函數,然后得到相應的結果。 函數形參 函數取得的參數是你提供給函數的值,這樣函數就可以利用這些值 做 一些事情。這些參數就像 變量一樣,只不過它們的值是在我們調用函數的時候定義的,而非在函數本身內賦值。 參數在函數定義的圓括號對內指定,用逗號分割。當我們調用函數的時候,我們以同樣的方式提 供值。注意我們使用過的朮語——函數中的參數名稱為 形參 而你提供給函數調用的值稱為 實 參。 使用函數形參 例7.2 使用函數形參 #!/usr/bin/python # Filename: func_param.py def printMax(a, b): if a > b: print a, 'is maximum' else: print b, 'is maximum' printMax(3, 4) # directly give literal values x=5 y=7 printMax(x, y) # give variables as arguments (源文件:code/func_param.py) 輸出 $ python func_param.py 4 is maximum 7 is maximum 它如何工作 這里,我們定義了一個稱為printMax的函數,這個函數需要兩個形參,叫做a和b。我們使用if..else 語句找出兩者之中較大的一個數,并且打印較大的那個數。 在第一個printMax使用中,我們直接把數,即實參,提供給函數。在第二個使用中,我們使用變 量調用函數。printMax(x, y)使實參x的值賦給形參a,實參y的值賦給形參b。在兩次調用中, printMax函數的工作完全相同。 局部變量 當你在函數定義內聲明變量的時候,它們與函數外具有相同名稱的其他變量沒有任何關系,即變 量名稱對于函數來說是 局部 的。這稱為變量的 作用域 。所有變量的作用域是它們被定義的塊, 從它們的名稱被定義的那點開始。 使用局部變量 例7.3 使用局部變量 #!/usr/bin/python # Filename: func_local.py def func(x): print 'x is', x x=2 print 'Changed local x to', x x = 50 func(x) print 'x is still', x (源文件:code/func_local.py) 輸出 $ python func_local.py x is 50 Changed local x to 2 x is still 50 它如何工作 在函數中,我們第一次使用x的 值 的時候,Python使用函數聲明的形參的值。 接下來,我們把值2賦給x。x是函數的局部變量。所以,當我們在函數內改變x的值的時候,在主 塊中定義的x不受影響。 在最后一個print語句中,我們証明了主塊中的x的值確實沒有受到影響。 使用global語句 如果你想要為一個定義在函數外的變量賦值,那麼你就得告訴Python這個變量名不是局部的,而 是 全局 的。我們使用global語句完成這一功能。沒有global語句,是不可能為定義在函數外的變量 賦值的。 你可以使用定義在函數外的變量的值(假設在函數內沒有同名的變量)。然而,我并不鼓勵你這 樣做,并且你應該盡量避免這樣做,因為這使得程序的讀者會不清楚這個變量是在哪里定義的。 使用global語句可以清楚地表明變量是在外面的塊定義的。 例7.4 使用global語句 #!/usr/bin/python # Filename: func_global.py def func(): global x print 'x is', x x=2 print 'Changed local x to', x x = 50 func() print 'Value of x is', x (源文件:code/func_global.py) 輸出 $ python func_global.py x is 50 Changed global x to 2 Value of x is 2 它如何工作 global語句被用來聲明x是全局的——因此,當我們在函數內把值賦給x的時候,這個變化也反映在 我們在主塊中使用x的值的時候。 你可以使用同一個global語句指定多個全局變量。例如global x, y, z。 默認參數值 對于一些函數,你可能希望它的一些參數是 可選 的,如果用戶不想要為這些參數提供值的話, 這些參數就使用默認值。這個功能借助于默認參數值完成。你可以在函數定義的形參名后加上賦 值運算符(=)和默認值,從而給形參指定默認參數值。 注意,默認參數值應該是一個參數。更加准確的說,默認參數值應該是不可變的——這會在后面 的章節中做詳細解釋。從現在開始,請記住這一點。 使用默認參數值 例7.5 使用默認參數值 #!/usr/bin/python # Filename: func_default.py def say(message, times = 1): print message * times say('Hello') say('World', 5) (源文件:code/func_default.py) 輸出 $ python func_default.py Hello WorldWorldWorldWorldWorld 它如何工作 名為say的函數用來打印一個字符串任意所需的次數。如果我們不提供一個值,那麼默認地,字符 串將只被打印一遍。我們通過給形參times指定默認參數值1來實現這一功能。 在第一次使用say的時候,我們只提供一個字符串,函數只打印一次字符串。在第二次使用say的 時候,我們提供了字符串和參數5,表明我們想要 說 這個字符串消息5遍。 重要 只有在形參表末尾的那些參數可以有默認參數值,即你不能在聲明函數形參的時候,先聲明有默 認值的形參而后聲明沒有默認值的形參。 這是因為賦給形參的值是根據位置而賦值的。例如,def func(a, b=5)是有效的,但是def func(a=5, b)是 無效 的。 關鍵參數 如果你的某個函數有許多參數,而你只想指定其中的一部分,那麼你可以通過命名來為這些參數 賦值——這被稱作 關鍵參數 ——我們使用名字(關鍵字)而不是位置(我們前面所一直使用的 方法)來給函數指定實參。 這樣做有兩個 優勢 ——一,由于我們不必擔心參數的順序,使用函數變得更加簡單了。二、假 設其他參數都有默認值,我們可以只給我們想要的那些參數賦值。 使用關鍵參數 例7.6 使用關鍵參數 #!/usr/bin/python # Filename: func_key.py def func(a, b=5, c=10): print 'a is', a, 'and b is', b, 'and c is', c func(3, 7) func(25, c=24) func(c=50, a=100) (源文件:code/func_key.py) 輸出 $ python func_key.py a is 3 and b is 7 and c is 10 a is 25 and b is 5 and c is 24 a is 100 and b is 5 and c is 50 它如何工作 名為func的函數有一個沒有默認值的參數,和兩個有默認值的參數。 在第一次使用函數的時候, func(3, 7),參數a得到值3,參數b得到值7,而參數c使用默認值10。 在第二次使用函數func(25, c=24)的時候,根據實參的位置變量a得到值25。根據命名,即關鍵參 數,參數c得到值24。變量b根據默認值,為5。 在第三次使用func(c=50, a=100)的時候,我們使用關鍵參數來完全指定參數值。注意,盡管函數 定義中,a在c之前定義,我們仍然可以在a之前指定參數c的值。 return語句 return語句用來從一個函數 返回 即跳出函數。我們也可選從函數 返回一個值 。 使用字面意義上的語句 例7.7 使用字面意義上的語句 #!/usr/bin/python # Filename: func_return.py def maximum(x, y): if x > y: return x else: return y print maximum(2, 3) (源文件:code/func_return.py) 輸出 $ python func_return.py 3 它如何工作 maximum函數返回參數中的最大值,在這里是提供給函數的數。它使用簡單的if..else語句來找出 較大的值,然后 返回 那個值。 注意,沒有返回值的return語句等價于return None。None是Python中表示沒有任何東西的特殊類 型。例如,如果一個變量的值為None,可以表示它沒有值。 除非你提供你自己的return語句,每個函數都在結尾暗含有return None語句。通過運行print someFunction(),你可以明白這一點,函數someFunction沒有使用return語句,如同: def someFunction(): pass pass語句在Python中表示一個空的語句塊。 DocStrings Python有一個很奇妙的特性,稱為 文檔字符串 ,它通常被簡稱為 docstrings 。DocStrings是一個重 要的工具,由于它幫助你的程序文檔更加簡單易懂,你應該盡量使用它。你甚至可以在程序運行 的時候,從函數恢復文檔字符串! 使用DocStrings 例7.8 使用DocStrings #!/usr/bin/python # Filename: func_doc.py def printMax(x, y): '''Prints the maximum of two numbers. The two values must be integers.''' x = int(x) # convert to integers, if possible y = int(y) if x > y: print x, 'is maximum' else: print y, 'is maximum' printMax(3, 5) print printMax.__doc__ (源文件:code/func_doc.py) 輸出 $ python func_doc.py 5 is maximum Prints the maximum of two numbers. The two values must be integers. 它如何工作 在函數的第一個邏輯行的字符串是這個函數的 文檔字符串 。注意,DocStrings也適用于模塊和 類,我們會在后面相應的章節學習它們。 文檔字符串的慣例是一個多行字符串,它的首行以大寫字母開始,句號結尾。第二行是空行,從 第三行開始是詳細的描述。 強烈建議 你在你的函數中使用文檔字符串時遵循這個慣例。 你可以使用__doc__(注意雙下划線)調用printMax函數的文檔字符串屬性(屬于函數的名稱)。 請記住Python把 每一樣東西 都作為對象,包括這個函數。我們會在后面的類一章學習更多關于對 象的知識。 如果你已經在Python中使用過help(),那麼你已經看到過DocStings的使用了!它所做的只是抓取函 數的__doc__屬性,然后整潔地展示給你。你可以對上面這個函數嘗試一下——只是在你的程序 中包括help(printMax)。記住按q退出help。 自動化工具也可以以同樣的方式從你的程序中提取文檔。因此,我 強烈建議 你對你所寫的任何 正式函數編寫文檔字符串。隨你的Python發行版附帶的pydoc命令,與help()類似地使用 DocStrings。 概括 我們已經學習了函數的很多方面的知識,不過注意還有一些方面我們沒有涉及。然而,我們已經 覆蓋了大多數在日常使用中,你可能用到的Python函數知識。 接下來,我們將學習如何創建和使用Python模塊。 第8章 模塊 目錄表 簡介 使用sys模塊 字節編譯的.pyc文件 from..import語句 模塊的__name__ 使用模塊的__name__ 制造你自己的模塊 創建你自己的模塊 from..import dir()函數 使用dir函數 概括 簡介 你已經學習了如何在你的程序中定義一次函數而重用代碼。如果你想要在其他程序中重用很多函 數,那麼你該如何編寫程序呢?你可能已經猜到了,答案是使用模塊。模塊基本上就是一個包含 了所有你定義的函數和變量的文件。為了在其他程序中重用模塊,模塊的文件名必須以.py為擴展 名。 模塊可以從其他程序 輸入 以便利用它的功能。這也是我們使用Python標准庫的方法。首先,我們 將學習如何使用標准庫模塊。 使用sys模塊 例8.1 使用sys模塊 #!/usr/bin/python # Filename: using_sys.py import sys print 'The command line arguments are:' for i in sys.argv: print i print '\n\nThe PYTHONPATH is', sys.path, '\n' (源文件:code/using_sys.py) 輸出 $ python using_sys.py we are arguments The command line arguments are: using_sys.py we are arguments The PYTHONPATH is ['/home/swaroop/byte/code', '/usr/lib/python23.zip', '/usr/lib/python2.3', '/usr/lib/python2.3/plat-linux2', '/usr/lib/python2.3/lib-tk', '/usr/lib/python2.3/lib-dynload', '/usr/lib/python2.3/site-packages', '/usr/lib/python2.3/site-packages/gtk-2.0'] 它如何工作 首先,我們利用import語句 輸入 sys模塊。基本上,這句語句告訴Python,我們想要使用這個模 塊。sys模塊包含了與Python解釋器和它的環境有關的函數。 當Python執行import sys語句的時候,它在sys.path變量中所列目錄中尋找sys.py模塊。如果找到了 這個文件,這個模塊的主塊中的語句將被運行,然后這個模塊將能夠被你 使用 。注意,初始化 過程僅在我們 第一次 輸入模塊的時候進行。另外,“sys”是“system”的縮寫。 sys模塊中的argv變量通過使用點號指明——sys.argv——這種方法的一個優勢是這個名稱不會與任 何在你的程序中使用的argv變量沖突。另外,它也清晰地表明了這個名稱是sys模塊的一部分。 sys.argv變量是一個字符串的 列表 (列表會在后面的章節詳細解釋)。特別地,sys.argv包含了 命 令行參數 的列表,即使用命令行傳遞給你的程序的參數。 如果你使用IDE編寫運行這些程序,請在菜單里尋找一個指定程序的命令行參數的方法。 這里,當我們執行python using_sys.py we are arguments的時候,我們使用python命令運行using_sys. py模塊,后面跟著的內容被作為參數傳遞給程序。Python為我們把它存儲在sys.argv變量中。 記住,腳本的名稱總是sys.argv列表的第一個參數。所以,在這里,'using_sys.py'是sys.argv [0]、'we'是sys.argv[1]、'are'是sys.argv[2]以及'arguments'是sys.argv[3]。注意,Python從0開始計數, 而非從1開始。 sys.path包含輸入模塊的目錄名列表。我們可以觀察到sys.path的第一個字符串是空的——這個空的 字符串表示當前目錄也是sys.path的一部分,這與PYTHONPATH環境變量是相同的。這意味著你 可以直接輸入位于當前目錄的模塊。否則,你得把你的模塊放在sys.path所列的目錄之一。 字節編譯的.pyc文件 輸入一個模塊相對來說是一個比較費時的事情,所以Python做了一些技巧,以便使輸入模塊更加 快一些。一種方法是創建 字節編譯的文件 ,這些文件以.pyc作為擴展名。字節編譯的文件與 Python變換程序的中間狀態有關(是否還記得Python如何工作的介紹?)。當你在下次從別的程 序輸入這個模塊的時候,.pyc文件是十分有用的——它會快得多,因為一部分輸入模塊所需的處 理已經完成了。另外,這些字節編譯的文件也是與平台無關的。所以,現在你知道了那些.pyc文 件事實上是什麼了。 from..import語句 如果你想要直接輸入argv變量到你的程序中(避免在每次使用它時打sys.),那麼你可以使用from sys import argv語句。如果你想要輸入所有sys模塊使用的名字,那麼你可以使用from sys import *語 句。這對于所有模塊都適用。一般說來,應該避免使用from..import而使用import語句,因為這樣 可以使你的程序更加易讀,也可以避免名稱的沖突。 模塊的__name__ 每個模塊都有一個名稱,在模塊中可以通過語句來找出模塊的名稱。這在一個場合特別有用—— 就如前面所提到的,當一個模塊被第一次輸入的時候,這個模塊的主塊將被運行。假如我們只想 在程序本身被使用的時候運行主塊,而在它被別的模塊輸入的時候不運行主塊,我們該怎麼做 呢?這可以通過模塊的__name__屬性完成。 使用模塊的__name__ 例8.2 使用模塊的__name__ #!/usr/bin/python # Filename: using_name.py if __name__ == '__main__': print 'This program is being run by itself' else: print 'I am being imported from another module' (源文件:code/using_name.py) 輸出 $ python using_name.py This program is being run by itself $ python >>> import using_name I am being imported from another module >>> 它如何工作 每個Python模塊都有它的__name__,如果它是'__main__',這說明這個模塊被用戶單獨運行,我 們可以進行相應的恰當操作。 制造你自己的模塊 創建你自己的模塊是十分簡單的,你一直在這樣做!每個Python程序也是一個模塊。你已經確保 它具有.py擴展名了。下面這個例子將會使它更加清晰。 創建你自己的模塊 例8.3 如何創建你自己的模塊 #!/usr/bin/python # Filename: mymodule.py def sayhi(): print 'Hi, this is mymodule speaking.' version = '0.1' # End of mymodule.py (源文件:code/mymodule.py) 上面是一個 模塊 的例子。你已經看到,它與我們普通的Python程序相比并沒有什麼特別之處。我 們接下來將看看如何在我們別的Python程序中使用這個模塊。 記住這個模塊應該被放置在我們輸入它的程序的同一個目錄中,或者在sys.path所列目錄之一。 #!/usr/bin/python # Filename: mymodule_demo.py import mymodule mymodule.sayhi() print 'Version', mymodule.version (源文件:code/mymodule_demo.py) 輸出 $ python mymodule_demo.py Hi, this is mymodule speaking. Version 0.1 它如何工作 注意我們使用了相同的點號來使用模塊的成員。Python很好地重用了相同的記號來,使我們這些 Python程序員不需要不斷地學習新的方法。 from..import 下面是一個使用from..import語法的版本。 #!/usr/bin/python # Filename: mymodule_demo2.py from mymodule import sayhi, version # Alternative: # from mymodule import * sayhi() print 'Version', version (源文件:code/mymodule_demo2.py) mymodule_demo2.py的輸出與mymodule_demo.py完全相同。 dir()函數 你可以使用內建的dir函數來列出模塊定義的標識符。標識符有函數、類和變量。 當你為dir()提供一個模塊名的時候,它返回模塊定義的名稱列表。如果不提供參數,它返回當前 模塊中定義的名稱列表。 使用dir函數 例8.4 使用dir函數 $ python >>> import sys >>> dir(sys) # get list of attributes for sys module ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode', 'meta_path','modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version', 'version_info', 'warnoptions'] >>> dir() # get list of attributes for current module ['__builtins__', '__doc__', '__name__', 'sys'] >>> >>> a = 5 # create a new variable 'a' >>> dir() ['__builtins__', '__doc__', '__name__', 'a', 'sys'] >>> >>> del a # delete/remove a name >>> >>> dir() ['__builtins__', '__doc__', '__name__', 'sys'] >>> 它如何工作 首先,我們來看一下在輸入的sys模塊上使用dir。我們看到它包含一個龐大的屬性列表。 接下來,我們不給dir函數傳遞參數而使用它——默認地,它返回當前模塊的屬性列表。注意,輸 入的模塊同樣是列表的一部分。 為了觀察dir的作用,我們定義一個新的變量a并且給它賦一個值,然后檢驗dir,我們觀察到在列 表中增加了以上相同的值。我們使用del語句刪除當前模塊中的變量/屬性,這個變化再一次反映 在dir的輸出中。 關于del的一點注釋——這個語句在運行后被用來 刪除 一個變量/名稱。在這個例子中,del a,你 將無法再使用變量a——它就好像從來沒有存在過一樣。 概括 模塊的用處在于它能為你在別的程序中重用它提供的服務和功能。Python附帶的標准庫就是這樣 一組模塊的例子。我們已經學習了如何使用這些模塊以及如何創造我們自己的模塊。 接下來,我們將學習一些有趣的概念,它們稱為數據結構。 第9章 數據結構 目錄表 簡介 列表 對象與類的快速入門 使用列表 元組 使用元組 元組與打印語句 字典 使用字典 序列 使用序列 參考 對象與參考 更多字符串的內容 字符串的方法 概括 簡介 數據結構基本上就是——它們是可以處理一些 數據 的 結構 。或者說,它們是用來存儲一組相關 數據的。 在Python中有三種內建的數據結構——列表、元組和字典。我們將會學習如何使用它們,以及它 們如何使編程變得簡單。 列表 list是處理一組有序項目的數據結構,即你可以在一個列表中存儲一個 序列 的項目。假想你有一 個購物列表,上面記載著你要買的東西,你就容易理解列表了。只不過在你的購物表上,可能每 樣東西都獨自占有一行,而在Python中,你在每個項目之間用逗號分割。 列表中的項目應該包括在方括號中,這樣Python就知道你是在指明一個列表。一旦你創建了一個 列表,你可以添加、刪除或是搜索列表中的項目。由于你可以增加或刪除項目,我們說列表是 可 變的 數據類型,即這種類型是可以被改變的。 對象與類的快速入門 盡管我一直推遲討論對象和類,但是現在對它們做一點解釋可以使你更好的理解列表。我們會在 相應的章節詳細探索這個主題。 列表是使用對象和類的一個例子。當你使用變量i并給它賦值的時候,比如賦整數5,你可以認為 你創建了一個類(類型)int的對象(實例)i。事實上,你可以看一下help(int)以更好地理解這一 點。 類也有方法,即僅僅為類而定義地函數。僅僅在你有一個該類的對象的時候,你才可以使用這些 功能。例如,Python為list類提供了append方法,這個方法讓你在列表尾添加一個項目。例如 mylist.append('an item')列表mylist中增加那個字符串。注意,使用點號來使用對象的方法。 一個類也有域,它是僅僅為類而定義的變量。僅僅在你有一個該類的對象的時候,你才可以使用 這些變量/名稱。類也通過點號使用,例如mylist.field。 使用列表 例9.1 使用列表 #!/usr/bin/python # Filename: using_list.py # This is my shopping list shoplist = ['apple', 'mango', 'carrot', 'banana'] print 'I have', len(shoplist),'items to purchase.' print 'These items are:', # Notice the comma at end of the line for item in shoplist: print item, print '\nI also have to buy rice.' shoplist.append('rice') print 'My shopping list is now', shoplist print 'I will sort my list now' shoplist.sort() print 'Sorted shopping list is', shoplist print 'The first item I will buy is', shoplist[0] olditem = shoplist[0] del shoplist[0] print 'I bought the', olditem print 'My shopping list is now', shoplist (源文件:code/using_list.py) 輸出 $ python using_list.py I have 4 items to purchase. These items are: apple mango carrot banana I also have to buy rice. My shopping list is now ['apple', 'mango', 'carrot', 'banana', 'rice'] I will sort my list now Sorted shopping list is ['apple', 'banana', 'carrot', 'mango', 'rice'] The first item I will buy is apple I bought the apple My shopping list is now ['banana', 'carrot', 'mango', 'rice'] 它如何工作 變量shoplist是某人的購物列表。在shoplist中,我們只存儲購買的東西的名字字符串,但是記住, 你可以在列表中添加 任何種類的對象 包括數甚至其他列表。 我們也使用了for..in循環在列表中各項目間遞歸。從現在開始,你一定已經意識到列表也是一個 序列。序列的特性會在后面的章節中討論。 注意,我們在print語句的結尾使用了一個 逗號 來消除每個print語句自動打印的換行符。這樣做有 點難看,不過確實簡單有效。 接下來,我們使用append方法在列表中添加了一個項目,就如前面已經討論過的一樣。然后我們 通過打印列表的內容來檢驗這個項目是否確實被添加進列表了。打印列表只需簡單地把列表傳遞 給print語句,我們可以得到一個整潔的輸出。 再接下來,我們使用列表的sort方法來對列表排序。需要理解的是,這個方法影響列表本身,而 不是返回一個修改后的列表——這與字符串工作的方法不同。這就是我們所說的列表是 可變的 而字符串是 不可變的 。 最后,但我們完成了在市場購買一樣東西的時候,我們想要把它從列表中刪除。我們使用del語句 來完成這個工作。這里,我們指出我們想要刪除列表中的哪個項目,而del語句為我們從列表中刪 除它。我們指明我們想要刪除列表中的第一個元素,因此我們使用del shoplist[0](記住,Python 從0開始計數)。 如果你想要知道列表對象定義的所有方法,可以通過help(list)獲得完整的知識。 元組 元組和列表十分類似,只不過元組和字符串一樣是 不可變的 即你不能修改元組。元組通過圓括 號中用逗號分割的項目定義。元組通常用在使語句或用戶定義的函數能夠安全地采用一組值的時 候,即被使用的元組的值不會改變。 使用元組 例9.2 使用元組 #!/usr/bin/python # Filename: using_tuple.py zoo = ('wolf', 'elephant', 'penguin') print 'Number of animals in the zoo is', len(zoo) new_zoo = ('monkey', 'dolphin', zoo) print 'Number of animals in the new zoo is', len(new_zoo) print 'All animals in new zoo are', new_zoo print 'Animals brought from old zoo are', new_zoo[2] print 'Last animal brought from old zoo is', new_zoo[2][2] (源文件:code/using_tuple.py) 輸出 $ python using_tuple.py Number of animals in the zoo is 3 Number of animals in the new zoo is 3 All animals in new zoo are ('monkey', 'dolphin', ('wolf', 'elephant', 'penguin')) Animals brought from old zoo are ('wolf', 'elephant', 'penguin') Last animal brought from old zoo is penguin 它如何工作 變量zoo是一個元組,我們看到len函數可以用來獲取元組的長度。這也表明元組也是一個序列。 由于老動物園關閉了,我們把動物轉移到新動物園。因此,new_zoo元組包含了一些已經在那里 的動物和從老動物園帶過來的動物。回到話題,注意元組之內的元組不會失去它的身份。 我們可以通過一對方括號來指明某個項目的位置從而來訪問元組中的項目,就像我們對列表的用 法一樣。這被稱作 索引 運算符。我們使用new_zoo[2]來訪問new_zoo中的第三個項目。我們使用 new_zoo[2][2]來訪問new_zoo元組的第三個項目的第三個項目。 含有0個或1個項目的元組。一個空的元組由一對空的圓括號組成,如myempty = ()。然而,含有 單個元素的元組就不那麼簡單了。你必須在第一個(唯一一個)項目后跟一個逗號,這樣Python 才能區分元組和表達式中一個帶圓括號的對象。即如果你想要的是一個包含項目2的元組的時 候,你應該指明singleton = (2 , )。 給Perl程序員的注釋 列表之中的列表不會失去它的身份,即列表不會像Perl中那樣被打散。同樣元組中的元組,或列 表中的元組,或元組中的列表等等都是如此。只要是Python,它們就只是使用另一個對象存儲的 對象。 元組與打印語句 元組最通常的用法是用在打印語句中,下面是一個例子: 例9.3 使用元組輸出 #!/usr/bin/python # Filename: print_tuple.py age = 22 name = 'Swaroop' print '%s is %d years old' % (name, age) print 'Why is %s playing with that python?' % name (源文件:code/print_tuple.py) 輸出 $ python print_tuple.py Swaroop is 22 years old Why is Swaroop playing with that python? 它如何工作 print語句可以使用跟著%符號的項目元組的字符串。這些字符串具備定制的功能。定制讓輸出滿 足某種特定的格式。定制可以是%s表示字符串或%d表示整數。元組必須按照相同的順序來對應 這些定制。 觀察我們使用的第一個元組,我們首先使用%s,這對應變量name,它是元組中的第一個項目。而 第二個定制是%d,它對應元組的第二個項目age。 Python在這里所做的是把元組中的每個項目轉換成字符串并且用字符串的值替換定制的位置。因 此%s被替換為變量name的值,依此類推。 print的這個用法使得編寫輸出變得極其簡單,它避免了許多字符串操作。它也避免了我們一直以 來使用的逗號。 在大多數時候,你可以只使用%s定制,而讓Python來提你處理剩余的事情。這種方法對數同樣奏 效。然而,你可能希望使用正確的定制,從而可以避免多一層的檢驗程序是否正確。 在第二個print語句中,我們使用了一個定制,后面跟著%符號后的單個項目——沒有圓括號。這 只在字符串中只有一個定制的時候有效。 字典 字典類似于你通過聯系人名字查找地址和聯系人詳細情況的地址簿,即,我們把鍵(名字)和值 (詳細情況)聯系在一起。注意,鍵必須是唯一的,就像如果有兩個人恰巧同名的話,你無法找 到正確的信息。 注意,你只能使用不可變的對象(比如字符串)來作為字典的鍵,但是你可以不可變或可變的對 象作為字典的值。基本說來就是,你應該只使用簡單的對象作為鍵。 鍵值對在字典中以這樣的方式標記:d = {key1 : value1, key2 : value2 }。注意它們的鍵/值對用冒號分 割,而各個對用逗號分割,所有這些都包括在花括號中。 記住字典中的鍵/值對是沒有順序的。如果你想要一個特定的順序,那麼你應該在使用前自己對 它們排序。 字典是dict類的實例/對象。 使用字典 例9.4 使用字典 #!/usr/bin/python # Filename: using_dict.py # 'ab' is short for 'a'ddress'b'ook ab = { 'Swaroop' : 'swaroopch@byteofpython.info', 'Larry' : 'larry@wall.org', 'Matsumoto' : 'matz@ruby-lang.org', 'Spammer' : 'spammer@hotmail.com' } print "Swaroop's address is %s" % ab['Swaroop'] # Adding a key/value pair ab['Guido'] = 'guido@python.org' # Deleting a key/value pair del ab['Spammer'] print '\nThere are %d contacts in the address-book\n' % len(ab) for name, address in ab.items(): print 'Contact %s at %s' % (name, address) if 'Guido' in ab: # OR ab.has_key('Guido') print "\nGuido's address is %s" % ab['Guido'] (源文件:code/using_dict.py) 輸出 $ python using_dict.py Swaroop's address is swaroopch@byteofpython.info There are 4 contacts in the address-book Contact Swaroop at swaroopch@byteofpython.info Contact Matsumoto at matz@ruby-lang.org Contact Larry at larry@wall.org Contact Guido at guido@python.org Guido's address is guido@python.org 它如何工作 我們使用已經介紹過的標記創建了字典ab。然后我們使用在列表和元組章節中已經討論過的索引 操作符來指定鍵,從而使用鍵/值對。我們可以看到字典的語法同樣十分簡單。 我們可以使用索引操作符來尋址一個鍵并為它賦值,這樣就增加了一個新的鍵/值對,就像在上 面的例子中我們對Guido所做的一樣。 我們可以使用我們的老朋友——del語句來刪除鍵/值對。我們只需要指明字典和用索引操作符指 明要刪除的鍵,然后把它們傳遞給del語句就可以了。執行這個操作的時候,我們無需知道那個鍵 所對應的值。 接下來,我們使用字典的items方法,來使用字典中的每個鍵/值對。這會返回一個元組的列表, 其中每個元組都包含一對項目——鍵與對應的值。我們抓取這個對,然后分別賦給for..in循環中 的變量name和address然后在for-塊中打印這些值。 我們可以使用in操作符來檢驗一個鍵/值對是否存在,或者使用dict類的has_key方法。你可以使用 help(dict)來查看dict類的完整方法列表。 關鍵字參數與字典。如果換一個角度看待你在函數中使用的關鍵字參數的話,你已經使用了字典 了!只需想一下——你在函數定義的參數列表中使用的鍵/值對。當你在函數中使用變量的時 候,它只不過是使用一個字典的鍵(這在編譯器設計的朮語中被稱作 符號表 )。 序列 列表、元組和字符串都是序列,但是序列是什麼,它們為什麼如此特別呢?序列的兩個主要特點 是索引操作符和切片操作符。索引操作符讓我們可以從序列中抓取一個特定項目。切片操作符讓 我們能夠獲取序列的一個切片,即一部分序列。 使用序列 例9.5 使用序列 #!/usr/bin/python # Filename: seq.py shoplist = ['apple', 'mango', 'carrot', 'banana'] # Indexing or 'Subscription' operation print 'Item 0 is', shoplist[0] print 'Item 1 is', shoplist[1] print 'Item 2 is', shoplist[2] print 'Item 3 is', shoplist[3] print 'Item -1 is', shoplist[-1] print 'Item -2 is', shoplist[-2] # Slicing on a list print 'Item 1 to 3 is', shoplist[1:3] print 'Item 2 to end is', shoplist[2:] print 'Item 1 to -1 is', shoplist[1:-1] print 'Item start to end is', shoplist[:] # Slicing on a string name = 'swaroop' print 'characters 1 to 3 is', name[1:3] print 'characters 2 to end is', name[2:] print 'characters 1 to -1 is', name[1:-1] print 'characters start to end is', name[:] (源文件:code/seq.py) 輸出 $ python seq.py Item 0 is apple Item 1 is mango Item 2 is carrot Item 3 is banana Item -1 is banana Item -2 is carrot Item 1 to 3 is ['mango', 'carrot'] Item 2 to end is ['carrot', 'banana'] Item 1 to -1 is ['mango', 'carrot'] Item start to end is ['apple', 'mango', 'carrot', 'banana'] characters 1 to 3 is wa characters 2 to end is aroop characters 1 to -1 is waroo characters start to end is swaroop 它如何工作 首先,我們來學習如何使用索引來取得序列中的單個項目。這也被稱作是下標操作。每當你用方 括號中的一個數來指定一個序列的時候,Python會為你抓取序列中對應位置的項目。記住, Python從0開始計數。因此,shoplist[0]抓取第一個項目,shoplist[3]抓取shoplist序列中的第四個元 素。 索引同樣可以是負數,在那樣的情況下,位置是從序列尾開始計算的。因此,shoplist[-1]表示序 列的最后一個元素而shoplist[-2]抓取序列的倒數第二個項目。 切片操作符是序列名后跟一個方括號,方括號中有一對可選的數字,并用冒號分割。注意這與你 使用的索引操作符十分相似。記住數是可選的,而冒號是必須的。 切片操作符中的第一個數(冒號之前)表示切片開始的位置,第二個數(冒號之后)表示切片到 哪里結束。如果不指定第一個數,Python就從序列首開始。如果沒有指定第二個數,則Python會 停止在序列尾。注意,返回的序列從開始位置 開始 ,剛好在 結束 位置之前結束。即開始位置是 包含在序列切片中的,而結束位置被排斥在切片外。 這樣,shoplist[1:3]返回從位置1開始,包括位置2,但是停止在位置3的一個序列切片,因此返回一 個含有兩個項目的切片。類似地,shoplist[:]返回整個序列的拷貝。 你可以用負數做切片。負數用在從序列尾開始計算的位置。例如,shoplist[:-1]會返回除了最后一 個項目外包含所有項目的序列切片。 使用Python解釋器交互地嘗試不同切片指定組合,即在提示符下你能夠馬上看到結果。序列的神 奇之處在于你可以用相同的方法訪問元組、列表和字符串。 參考 當你創建一個對象并給它賦一個變量的時候,這個變量僅僅 參考 那個對象,而不是表示這個對 象本身!也就是說,變量名指向你計算機中存儲那個對象的內存。這被稱作名稱到對象的綁定。 一般說來,你不需要擔心這個,只是在參考上有些細微的效果需要你注意。這會通過下面這個例 子加以說明。 對象與參考 例9.6 對象與參考 #!/usr/bin/python # Filename: reference.py print 'Simple Assignment' shoplist = ['apple', 'mango', 'carrot', 'banana'] mylist = shoplist # mylist is just another name pointing to the same object! del shoplist[0] print 'shoplist is', shoplist print 'mylist is', mylist # notice that both shoplist and mylist both print the same list without # the 'apple' confirming that they point to the same object print 'Copy by making a full slice' mylist = shoplist[:] # make a copy by doing a full slice del mylist[0] # remove first item print 'shoplist is', shoplist print 'mylist is', mylist # notice that now the two lists are different (源文件:code/reference.py) 輸出 $ python reference.py Simple Assignment shoplist is ['mango', 'carrot', 'banana'] mylist is ['mango', 'carrot', 'banana'] Copy by making a full slice shoplist is ['mango', 'carrot', 'banana'] mylist is ['carrot', 'banana'] 它如何工作 大多數解釋已經在程序的注釋中了。你需要記住的只是如果你想要復制一個列表或者類似的序列 或者其他復雜的對象(不是如整數那樣的簡單 對象 ),那麼你必須使用切片操作符來取得拷 貝。如果你只是想要使用另一個變量名,兩個名稱都 參考 同一個對象,那麼如果你不小心的 話,可能會引來各種麻煩。 給Perl程序員的注釋 記住列表的賦值語句不創建拷貝。你得使用切片操作符來建立序列的拷貝。 更多字符串的內容 我們已經在前面詳細討論了字符串。我們還需要知道什麼呢?那麼,你是否知道字符串也是對 象,同樣具有方法。這些方法可以完成包括檢驗一部分字符串和去除空格在內的各種工作。 你在程序中使用的字符串都是str類的對象。這個類的一些有用的方法會在下面這個例子中說明。 如果要了解這些方法的完整列表,請參見help(str)。 字符串的方法 例9.7 字符串的方法 #!/usr/bin/python # Filename: str_methods.py name = 'Swaroop' # This is a string object if name.startswith('Swa'): print 'Yes, the string starts with "Swa"' if 'a' in name: print 'Yes, it contains the string "a"' if name.find('war') != -1: print 'Yes, it contains the string "war"' delimiter = '_*_' mylist = ['Brazil', 'Russia', 'India', 'China'] print delimiter.join(mylist) (源文件:code/str_methods.py) 輸出 $ python str_methods.py Yes, the string starts with "Swa" Yes, it contains the string "a" Yes, it contains the string "war" Brazil_*_Russia_*_India_*_China 它如何工作 這里,我們看到使用了許多字符串方法。startwith方法是用來測試字符串是否以給定字符串開 始。in操作符用來檢驗一個給定字符串是否為另一個字符串的一部分。 find方法用來找出給定字符串在另一個字符串中的位置,或者返回-1以表示找不到子字符串。str 類也有以一個作為分隔符的字符串join序列的項目的整潔的方法,它返回一個生成的大字符串。 概括 我們已經詳細探討了多種Python內建的數據結構。這些數據結構將是編寫程序時至關重要的部 分。 現在我們已經掌握了很多Python的基本知識,我們接下來將學習如何設計和編寫一個實用的 Python程序。 第10章 解決問題——編寫一個Python腳本 目錄表 問題 解決方案 版本一 版本二 版本三 版本四 進一步優化 軟件開發過程 概括 我們已經研究了Python語言的眾多內容,現在我們將來學習一下怎麼把這些內容結合起來。我們 將設計編寫一個能夠 做 一些確實有用的事情的程序。 問題 我提出的問題是: 我想要一個可以為我的所有重要文件創建備份的程序。 盡管這是一個簡單的問題,但是問題本身并沒有給我們足夠的信息來解決它。進一步的分析是必 需的。例如,我們如何確定該備份哪些文件?備份保存在哪里?我們怎麼樣存儲備份? 在恰當地分析了這個問題之后,我們開始設計我們的程序。我們列了一張表,表示我們的程序應 該如何工作。對于這個問題,我已經創建了下面這個列表以說明 我 如何讓它工作。如果是你設 計的話,你可能不會這樣來解決問題——每個人都有其做事的方法,這很正常。 1. 需要備份的文件和目錄由一個列表指定。 2. 備份應該保存在主備份目錄中。 3. 文件備份成一個zip文件。 4. zip存檔的名稱是當前的日期和時間。 5. 我們使用標准的zip命令,它通常默認地隨Linux/Unix發行版提供。Windows用戶可以使用 Info-Zip程序。注意你可以使用任何地存檔命令,只要它有命令行界面就可以了,那樣的話 我們可以從我們的腳本中傳遞參數給它。 解決方案 當我們基本完成程序的設計,我們就可以編寫代碼了,它是對我們的解決方案的實施。 版本一 例10.1 備份腳本——版本一 #!/usr/bin/python # Filename: backup_ver1.py import os import time # 1. The files and directories to be backed up are specified in a list. source = ['/home/swaroop/byte', '/home/swaroop/bin'] # If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that # 2. The backup must be stored in a main backup directory target_dir = '/mnt/e/backup/' # Remember to change this to what you will be using # 3. The files are backed up into a zip file. # 4. The name of the zip archive is the current date and time target = target_dir + time.strftime('%Y%m%d%H%M%S') + '.zip' # 5. We use the zip command (in Unix/Linux) to put the files in a zip archive zip_command = "zip -qr '%s' %s" % (target, ' '.join(source)) # Run the backup if os.system(zip_command) == 0: print 'Successful backup to', target else: print 'Backup FAILED' (源文件:code/backup_ver1.py) 輸出 $ python backup_ver1.py Successful backup to /mnt/e/backup/20041208073244.zip 現在,我們已經處于測試環節了,在這個環節,我們測試我們的程序是否正確工作。如果它與我 們所期望的不一樣,我們就得調試我們的程序,即消除程序中的 瑕疵 (錯誤)。 它如何工作 接下來你將看到我們如何把 設計 一步一步地轉換為 代碼 。 我們使用了os和time模塊,所以我們輸入它們。然后,我們在source列表中指定需要備份的文件和 目錄。目標目錄是我們想要存儲備份文件的地方,它由target_dir變量指定。zip歸檔的名稱是目前 的日期和時間,我們使用time.strftime()函數獲得。它還包括.zip擴展名,將被保存在target_dir目錄 中。 time.strftime()函數需要我們在上面的程序中使用的那種定制。%Y會被無世紀的年份所替代。%m 會被01到12之間的一個十進制月份數替代,其他依次類推。這些定制的詳細情況可以在《Python 參考手冊》中獲得。《Python參考手冊》包含在你的Python發行版中。注意這些定制與用于print 語句的定制(%后跟一個元組)類似(但不完全相同) 我們使用加法操作符來 級連 字符串,即把兩個字符串連接在一起返回一個新的字符串。通過這 種方式,我們創建了目標zip文件的名稱。接著我們創建了zip_command字符串,它包含我們將要 執行的命令。你可以在shell(Linux終端或者DOS提示符)中運行它,以檢驗它是否工作。 zip命令有一些選項和參數。-q選項用來表示zip命令安靜地工作。-r選項表示zip命令對目錄遞歸地 工作,即它包括子目錄以及子目錄中的文件。兩個選項可以組合成縮寫形式-qr。選項后面跟著待 創建的zip歸檔的名稱,然后再是待備份的文件和目錄列表。我們使用已經學習過的字符串join方 法把source列表轉換為字符串。 最后,我們使用os.system函數 運行 命令,利用這個函數就好像在 系統 中運行命令一樣。即在shell 中運行命令——如果命令成功運行,它返回0,否則它返回錯誤號。 根據命令的輸出,我們打印對應的消息,顯示備份是否創建成功。好了,就是這樣我們已經創建 了一個腳本來對我們的重要文件做備份! 給Windows用戶的注釋 你可以把source列表和target目錄設置成任何文件和目錄名,但是在Windows中你得小心一些。問 題是Windows把反斜杠(\)作為目錄分隔符,而Python用反斜杠表示轉義符! 所以,你得使用轉義符來表示反斜杠本身或者使用自然字符串。例如,使用'C:\\Documents'或r'C: \Documents'而不是'C:\Documents'——你在使用一個不知名的轉義符\D! 現在我們已經有了一個可以工作的備份腳本,我們可以在任何我們想要建立文件備份的時候使用 它。建議Linux/Unix用戶使用前面介紹的可執行的方法,這樣就可以在任何地方任何時候運行備 份腳本了。這被稱為軟件的實施環節或開發環節。 上面的程序可以正確工作,但是(通常)第一個程序并不是與你所期望的完全一樣。例如,可能 有些問題你沒有設計恰當,又或者你在輸入代碼的時候發生了一點錯誤,等等。正常情況下,你 應該回到設計環節或者調試程序。 版本二 第一個版本的腳本可以工作。然而,我們可以對它做些優化以便讓它在我們的日常工作中變得更 好。這稱為軟件的維護環節。 我認為優化之一是采用更好的文件名機制——使用 時間 作為文件名,而當前的 日期 作為目錄 名,存放在主備份目錄中。這樣做的一個優勢是你的備份會以等級結構存儲,因此它就更加容易 管理了。另外一個優勢是文件名的長度也可以變短。還有一個優勢是采用各自獨立的文件夾可以 幫助你方便地檢驗你是否在每一天創建了備份,因為只有在你創建了備份,才會出現那天的目 錄。 例10.2 備份腳本——版本二 #!/usr/bin/python # Filename: backup_ver2.py import os import time # 1. The files and directories to be backed up are specified in a list. source = ['/home/swaroop/byte', '/home/swaroop/bin'] # If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that # 2. The backup must be stored in a main backup directory target_dir = '/mnt/e/backup/' # Remember to change this to what you will be using # 3. The files are backed up into a zip file. # 4. The current day is the name of the subdirectory in the main directory today = target_dir + time.strftime('%Y%m%d') # The current time is the name of the zip archive now = time.strftime('%H%M%S') # Create the subdirectory if it isn't already there if not os.path.exists(today): os.mkdir(today) # make directory print 'Successfully created directory', today # The name of the zip file target = today + os.sep + now + '.zip' # 5. We use the zip command (in Unix/Linux) to put the files in a zip archive zip_command = "zip -qr '%s' %s" % (target, ' '.join(source)) # Run the backup if os.system(zip_command) == 0: print 'Successful backup to', target else: print 'Backup FAILED' (源文件:code/backup_ver2.py) 輸出 $ python backup_ver2.py Successfully created directory /mnt/e/backup/20041208 Successful backup to /mnt/e/backup/20041208/080020.zip $ python backup_ver2.py Successful backup to /mnt/e/backup/20041208/080428.zip 它如何工作 兩個程序的大部分是相同的。改變的部分主要是使用os.exists函數檢驗在主備份目錄中是否有以當 前日期作為名稱的目錄。如果沒有,我們使用os.mkdir函數創建。 注意os.sep變量的用法——這會根據你的操作系統給出目錄分隔符,即在Linux、Unix下它是'/', 在Windows下它是'\\',而在Mac OS下它是':'。使用os.sep而非直接使用字符,會使我們的程序具有 移植性,可以在上述這些系統下工作。 版本三 第二個版本在我做較多備份的時候還工作得不錯,但是如果有極多備份的時候,我發現要區分每 個備份是干什麼的,會變得十分困難!例如,我可能對程序或者演講稿做了一些重要的改變,于 是我想要把這些改變與zip歸檔的名稱聯系起來。這可以通過在zip歸檔名上附帶一個用戶提供的 注釋來方便地實現。 例10.3 備份腳本——版本三(不工作!) #!/usr/bin/python # Filename: backup_ver3.py import os import time # 1. The files and directories to be backed up are specified in a list. source = ['/home/swaroop/byte', '/home/swaroop/bin'] # If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that # 2. The backup must be stored in a main backup directory target_dir = '/mnt/e/backup/' # Remember to change this to what you will be using # 3. The files are backed up into a zip file. # 4. The current day is the name of the subdirectory in the main directory today = target_dir + time.strftime('%Y%m%d') # The current time is the name of the zip archive now = time.strftime('%H%M%S') # Take a comment from the user to create the name of the zip file comment = raw_input('Enter a comment --> ') if len(comment) == 0: # check if a comment was entered target = today + os.sep + now + '.zip' else: target = today + os.sep + now + '_' + comment.replace(' ', '_') + '.zip' # Create the subdirectory if it isn't already there if not os.path.exists(today): os.mkdir(today) # make directory print 'Successfully created directory', today # 5. We use the zip command (in Unix/Linux) to put the files in a zip archive zip_command = "zip -qr '%s' %s" % (target, ' '.join(source)) # Run the backup if os.system(zip_command) == 0: print 'Successful backup to', target else: print 'Backup FAILED' (源文件:code/backup_ver3.py) 輸出 $ python backup_ver3.py File "backup_ver3.py", line 25 target = today + os.sep + now + '_' + ^ SyntaxError: invalid syntax 它如何(不)工作 這個程序不工作!Python說有一個語法錯誤,這意味著腳本不滿足Python可以識別的結構。當我 們觀察Python給出的錯誤的時候,它也告訴了我們它檢測出錯誤的位置。所以我們從那行開始 調 試 我們的程序。 通過仔細的觀察,我們發現一個邏輯行被分成了兩個物理行,但是我們并沒有指明這兩個物理行 屬于同一邏輯行。基本上,Python發現加法操作符(+)在那一邏輯行沒有任何操作數,因此它 不知道該如何繼續。記住我們可以使用物理行尾的反斜杠來表示邏輯行在下一物理行繼續。所 以,我們修正了程序。這被稱為修訂。 版本四 例10.4 備份腳本——版本四 #!/usr/bin/python # Filename: backup_ver4.py import os import time # 1. The files and directories to be backed up are specified in a list. source = ['/home/swaroop/byte', '/home/swaroop/bin'] # If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that # 2. The backup must be stored in a main backup directory target_dir = '/mnt/e/backup/' # Remember to change this to what you will be using # 3. The files are backed up into a zip file. # 4. The current day is the name of the subdirectory in the main directory today = target_dir + time.strftime('%Y%m%d') # The current time is the name of the zip archive now = time.strftime('%H%M%S') # Take a comment from the user to create the name of the zip file comment = raw_input('Enter a comment --> ') if len(comment) == 0: # check if a comment was entered target = today + os.sep + now + '.zip' else: target = today + os.sep + now + '_' + \ comment.replace(' ', '_') + '.zip' # Notice the backslash! # Create the subdirectory if it isn't already there if not os.path.exists(today): os.mkdir(today) # make directory print 'Successfully created directory', today # 5. We use the zip command (in Unix/Linux) to put the files in a zip archive zip_command = "zip -qr '%s' %s" % (target, ' '.join(source)) # Run the backup if os.system(zip_command) == 0: print 'Successful backup to', target else: print 'Backup FAILED' (源文件:code/backup_ver4.py) 輸出 $ python backup_ver4.py Enter a comment --> added new examples Successful backup to /mnt/e/backup/20041208/082156_added_new_examples.zip $ python backup_ver4.py Enter a comment --> Successful backup to /mnt/e/backup/20041208/082316.zip 它如何工作 這個程序現在工作了!讓我們看一下版本三中作出的實質性改進。我們使用raw_input函數得到用 戶的注釋,然后通過len函數找出輸入的長度以檢驗用戶是否確實輸入了什麼東西。如果用戶只是 按了回車(比如這只是一個慣例備份,沒有做什麼特別的修改),那麼我們就如之前那樣繼續操 作。 然而,如果提供了注釋,那麼它會被附加到zip歸檔名,就在.zip擴展名之前。注意我們把注釋中 的空格替換成下划線——這是因為處理這樣的文件名要容易得多。 進一步優化 對于大多數用戶來說,第四個版本是一個滿意的工作腳本了,但是它仍然有進一步改進的空間。 比如,你可以在程序中包含 交互 程度——你可以用-v選項來使你的程序更具交互性。 另一個可能的改進是使文件和目錄能夠通過命令行直接傳遞給腳本。我們可以通過sys.argv列表來 獲取它們,然后我們可以使用list類提供的extend方法把它們加到source列表中去。 我還希望有的一個優化是使用tar命令替代zip命令。這樣做的一個優勢是在你結合使用tar和gzip命 令的時候,備份會更快更小。如果你想要在Windows中使用這些歸檔,WinZip也能方便地處理這 些.tar.gz文件。tar命令在大多數Linux/Unix系統中都是默認可用的。Windows用戶也可以下載安裝 它。 命令字符串現在將稱為: tar = 'tar -cvzf %s %s -X /home/swaroop/excludes.txt' % (target, ' '.join(srcdir)) 選項解釋如下: ● -c表示創建一個歸檔。 ● -v表示交互,即命令更具交互性。 ● -z表示使用gzip濾波器。 ● -f表示強迫創建歸檔,即如果已經有一個同名文件,它會被替換。 ● -X表示含在指定文件名列表中的文件會被排除在備份之外。例如,你可以在文件中指定 *~,從而不讓備份包括所有以~結尾的文件。 重要 最理想的創建這些歸檔的方法是分別使用zipfile和tarfile。它們是Python標准庫的一部分,可以供 你使用。使用這些庫就避免了使用os.system這個不推荐使用的函數,它容易引發嚴重的錯誤。 然而,我在本節中使用os.system的方法來創建備份,這純粹是為了教學的需要。這樣的話,例子 就可以簡單到讓每個人都能夠理解,同時也已經足夠用了。 軟件開發過程 現在,我們已經走過了編寫一個軟件的各個環節。這些環節可以概括如下: 1. 什麼(分析) 2. 如何(設計) 3. 編寫(實施) 4. 測試(測試與調試) 5. 使用(實施或開發) 6. 維護(優化) 重要 我們創建這個備份腳本的過程是編寫程序的推荐方法——進行分析與設計。開始時實施一個簡單 的版本。對它進行測試與調試。使用它以確信它如預期那樣地工作。再增加任何你想要的特性, 根據需要一次次重復這個編寫-測試-使用的周期。記住“軟件是長出來的,而不是建造的”。 概括 我們已經學習如何創建我們自己的Python程序/腳本,以及在編寫這個程序中所設計到的不同的狀 態。你可以發現它們在創建你自己的程序的時候會十分有用,讓你對Python以及解決問題都變得 更加得心應手。 接下來,我們將討論面向對象的編程。 第11章 面向對象的編程 目錄表 簡介 self 類 創建一個類 對象的方法 使用對象的方法 __init__方法 使用__init__方法 類與對象的變量 使用類與對象的變量 繼承 使用繼承 概括 簡介 到目前為止,在我們的程序中,我們都是根據操作數據的函數或語句塊來設計程序的。這被稱為 面向過程的 編程。還有一種把數據和功能結合起來,用稱為對象的東西包裹起來組織程序的方 法。這種方法稱為 面向對象的 編程理念。在大多數時候你可以使用過程性編程,但是有些時候 當你想要編寫大型程序或是尋求一個更加合適的解決方案的時候,你就得使用面向對象的編程技 朮。 類和對象是面向對象編程的兩個主要方面。類創建一個新類型,而對象這個類的 實例 。這類似 于你有一個int類型的變量,這存儲整數的變量是int類的實例(對象)。 給C/C++/Java/C#程序員的注釋 注意,即便是整數也被作為對象(屬于int類)。這和C++、Java(1.5版之前)把整數純粹作為類 型是不同的。通過help(int)了解更多這個類的詳情。 C#和Java 1.5程序員會熟悉這個概念,因為它 類似與 封裝與解封裝 的概念。 對象可以使用普通的 屬于 對象的變量存儲數據。屬于一個對象或類的變量被稱為域。對象也可 以使用 屬于 類的函數來具有功能。這樣的函數被稱為類的方法。這些朮語幫助我們把它們與孤 立的函數和變量區分開來。域和方法可以合稱為類的屬性。 域有兩種類型——屬于每個實例/類的對象或屬于類本身。它們分別被稱為實例變量和類變量。 類使用class關鍵字創建。類的域和方法被列在一個縮進塊中。 self 類的方法與普通的函數只有一個特別的區別——它們必須有一個額外的第一個參數名稱,但是在 調用這個方法的時候你不為這個參數賦值,Python會提供這個值。這個特別的變量指對象本身, 按照慣例它的名稱是self。 雖然你可以給這個參數任何名稱,但是 強烈建議 你使用self這個名稱——其他名稱都是不贊成你 使用的。使用一個標准的名稱有很多優點——你的程序讀者可以迅速識別它,如果使用self的話, 還有些IDE(集成開發環境)也可以幫助你。 給C++/Java/C#程序員的注釋 Python中的self等價于C++中的self指針和Java、C#中的this參考。 你一定很奇怪Python如何給self賦值以及為何你不需要給它賦值。舉一個例子會使此變得清晰。假 如你有一個類稱為MyClass和這個類的一個實例MyObject。當你調用這個對象的方法MyObject. method(arg1, arg2)的時候,這會由Python自動轉為MyClass.method(MyObject, arg1, arg2)——這就是 self的原理了。 這也意味著如果你有一個不需要參數的方法,你還是得給這個方法定義一個self參數。 類 一個盡可能簡單的類如下面這個例子所示。 創建一個類 例11.1 創建一個類 #!/usr/bin/python # Filename: simplestclass.py class Person: pass # An empty block p = Person() print p (源文件:code/simplestclass.py) 輸出 $ python simplestclass.py <__main__.Person instance at 0xf6fcb18c> 它如何工作 我們使用class語句后跟類名,創建了一個新的類。這后面跟著一個縮進的語句塊形成類體。在這 個例子中,我們使用了一個空白塊,它由pass語句表示。 接下來,我們使用類名后跟一對圓括號來創建一個對象/實例。(我們將在下面的章節中學習更 多的如何創建實例的方法)。為了驗証,我們簡單地打印了這個變量的類型。它告訴我們我們已 經在__main__模塊中有了一個Person類的實例。 可以注意到存儲對象的計算機內存地址也打印了出來。這個地址在你的計算機上會是另外一個 值,因為Python可以在任何空位存儲對象。 對象的方法 我們已經討論了類/對象可以擁有像函數一樣的方法,這些方法與函數的區別只是一個額外的self 變量。現在我們來學習一個例子。 使用對象的方法 例11.2 使用對象的方法 #!/usr/bin/python # Filename: method.py class Person: def sayHi(self): print 'Hello, how are you?' p = Person() p.sayHi() # This short example can also be written as Person().sayHi() (源文件:code/method.py) 輸出 $ python method.py Hello, how are you? 它如何工作 這里我們看到了self的用法。注意sayHi方法沒有任何參數,但仍然在函數定義時有self。 __init__方法 在Python的類中有很多方法的名字有特殊的重要意義。現在我們將學習__init__方法的意義。 __init__方法在類的一個對象被建立時,馬上運行。這個方法可以用來對你的對象做一些你希望 的 初始化 。注意,這個名稱的開始和結尾都是雙下划線。 使用__init__方法 例11.3 使用__init__方法 #!/usr/bin/python # Filename: class_init.py class Person: def __init__(self, name): self.name = name def sayHi(self): print 'Hello, my name is', self.name p = Person('Swaroop') p.sayHi() # This short example can also be written as Person('Swaroop').sayHi() (源文件:code/class_init.py) 輸出 $ python class_init.py Hello, my name is Swaroop 它如何工作 這里,我們把__init__方法定義為取一個參數name(以及普通的參數self)。在這個__init__里,我 們只是創建一個新的域,也稱為name。注意它們是兩個不同的變量,盡管它們有相同的名字。點 號使我們能夠區分它們。 最重要的是,我們沒有專門調用__init__方法,只是在創建一個類的新實例的時候,把參數包括 在圓括號內跟在類名后面,從而傳遞給__init__方法。這是這種方法的重要之處。 現在,我們能夠在我們的方法中使用self.name域。這在sayHi方法中得到了驗証。 給C++/Java/C#程序員的注釋 __init__方法類似于C++、C#和Java中的 constructor 。 類與對象的方法 我們已經討論了類與對象的功能部分,現在我們來看一下它的數據部分。事實上,它們只是與類 和對象的名稱空間 綁定 的普通變量,即這些名稱只在這些類與對象的前提下有效。 有兩種類型的 域 ——類的變量和對象的變量,它們根據是類還是對象 擁有 這個變量而區分。 類的變量 由一個類的所有對象(實例)共享使用。只有一個類變量的拷貝,所以當某個對象對類 的變量做了改動的時候,這個改動會反映到所有其他的實例上。 對象的變量 由類的每個對象/實例擁有。因此每個對象有自己對這個域的一份拷貝,即它們不是 共享的,在同一個類的不同實例中,雖然對象的變量有相同的名稱,但是是互不相關的。通過一 個例子會使這個易于理解。 使用類與對象的變量 例11.4 使用類與對象的變量 #!/usr/bin/python # Filename: objvar.py class Person: '''Represents a person.''' population = 0 def __init__(self, name): '''Initializes the person's data.''' self.name = name print '(Initializing %s)' % self.name # When this person is created, he/she # adds to the population Person.population += 1 def __del__(self): '''I am dying.''' print '%s says bye.' % self.name Person.population -= 1 if Person.population == 0: print 'I am the last one.' else: print 'There are still %d people left.' % Person.population def sayHi(self): '''Greeting by the person. Really, that's all it does.''' print 'Hi, my name is %s.' % self.name def howMany(self): '''Prints the current population.''' if Person.population == 1: print 'I am the only person here.' else: print 'We have %d persons here.' % Person.population swaroop = Person('Swaroop') swaroop.sayHi() swaroop.howMany() kalam = Person('Abdul Kalam') kalam.sayHi() kalam.howMany() swaroop.sayHi() swaroop.howMany() (源文件:code/objvar.py) 輸出 $ python objvar.py (Initializing Swaroop) Hi, my name is Swaroop. I am the only person here. (Initializing Abdul Kalam) Hi, my name is Abdul Kalam. We have 2 persons here. Hi, my name is Swaroop. We have 2 persons here. Abdul Kalam says bye. There are still 1 people left. Swaroop says bye. I am the last one. 它如何工作 這是一個很長的例子,但是它有助于說明類與對象的變量的本質。這里,population屬于Person 類,因此是一個類的變量。name變量屬于對象(它使用self賦值)因此是對象的變量。 觀察可以發現__init__方法用一個名字來初始化Person實例。在這個方法中,我們讓population增加 1,這是因為我們增加了一個人。同樣可以發現,self.name的值根據每個對象指定,這表明了它作 為對象的變量的本質。 記住,你只能使用self變量來參考同一個對象的變量和方法。這被稱為 屬性參考 。 在這個程序中,我們還看到docstring對于類和方法同樣有用。我們可以在運行時使用Person. __doc__和Person.sayHi.__doc__來分別訪問類與方法的文檔字符串。 就如同__init__方法一樣,還有一個特殊的方法__del__,它在對象消逝的時候被調用。對象消逝 即對象不再被使用,它所占用的內存將返回給系統作它用。在這個方法里面,我們只是簡單地把 Person.population減1。 當對象不再被使用時,__del__方法運行,但是很難保証這個方法究竟在 什麼時候 運行。如果你 想要指明它的運行,你就得使用del語句,就如同我們在以前的例子中使用的那樣。 給C++/Java/C#程序員的注釋 Python中所有的類成員(包括數據成員)都是 公共的 ,所有的方法都是 有效的 。 只有一個例外:如果你使用的數據成員名稱以 雙下划線前綴 比如__privatevar,Python的名稱管理 體系會有效地把它作為私有變量。 這樣就有一個慣例,如果某個變量只想在類或對象中使用,就應該以單下划線前綴。而其他的名 稱都將作為公共的,可以被其他類/對象使用。記住這只是一個慣例,并不是Python所要求的(與 雙下划線前綴不同)。 同樣,注意__del__方法與 destructor 的概念類似。 繼承 面向對象的編程帶來的主要好處之一是代碼的重用,實現這種重用的方法之一是通過 繼承 機 制。繼承完全可以理解成類之間的 類型和子類型 關系。 假設你想要寫一個程序來記錄學校之中的教師和學生情況。他們有一些共同屬性,比如姓名、年 齡和地址。他們也有專有的屬性,比如教師的薪水、課程和假期,學生的成績和學費。 你可以為教師和學生建立兩個獨立的類來處理它們,但是這樣做的話,如果要增加一個新的共有 屬性,就意味著要在這兩個獨立的類中都增加這個屬性。這很快就會顯得不實用。 一個比較好的方法是創建一個共同的類稱為SchoolMember然后讓教師和學生的類 繼承 這個共同 的類。即它們都是這個類型(類)的子類型,然后我們再為這些子類型添加專有的屬性。 使用這種方法有很多優點。如果我們增加/改變了SchoolMember中的任何功能,它會自動地反映 到子類型之中。例如,你要為教師和學生都增加一個新的身份証域,那麼你只需簡單地把它加到 SchoolMember類中。然而,在一個子類型之中做的改動不會影響到別的子類型。另外一個優點是 你可以把教師和學生對象都作為SchoolMember對象來使用,這在某些場合特別有用,比如統計學 校成員的人數。一個子類型在任何需要父類型的場合可以被替換成父類型,即對象可以被視作是 父類的實例,這種現象被稱為多態現象。 另外,我們會發現在 重用 父類的代碼的時候,我們無需在不同的類中重復它。而如果我們使用 獨立的類的話,我們就不得不這麼做了。 在上述的場合中,SchoolMember類被稱為 基本類 或 超類 。而Teacher和Student類被稱為 導出類 或 子類 。 現在,我們將學習一個例子程序。 使用繼承 例11.5 使用繼承 #!/usr/bin/python http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch11s07.html(第 1/3 頁)2010-10-3 18:09:55 簡明 Python 教程 / 面向對象的編程 / 繼承 # Filename: inherit.py class SchoolMember: '''Represents any school member.''' def __init__(self, name, age): self.name = name self.age = age print '(Initialized SchoolMember: %s)' % self.name def tell(self): '''Tell my details.''' print 'Name:"%s" Age:"%s"' % (self.name, self.age), class Teacher(SchoolMember): '''Represents a teacher.''' def __init__(self, name, age, salary): SchoolMember.__init__(self, name, age) self.salary = salary print '(Initialized Teacher: %s)' % self.name def tell(self): SchoolMember.tell(self) print 'Salary: "%d"' % self.salary class Student(SchoolMember): '''Represents a student.''' def __init__(self, name, age, marks): SchoolMember.__init__(self, name, age) self.marks = marks print '(Initialized Student: %s)' % self.name def tell(self): SchoolMember.tell(self) print 'Marks: "%d"' % self.marks t = Teacher('Mrs. Shrividya', 40, 30000) s = Student('Swaroop', 22, 75) print # prints a blank line members = [t, s] for member in members: member.tell() # works for both Teachers and Students http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch11s07.html(第 2/3 頁)2010-10-3 18:09:55 簡明 Python 教程 / 面向對象的編程 / 繼承 (源文件:code/inherit.py) 輸出 $ python inherit.py (Initialized SchoolMember: Mrs. Shrividya) (Initialized Teacher: Mrs. Shrividya) (Initialized SchoolMember: Swaroop) (Initialized Student: Swaroop) Name:"Mrs. Shrividya" Age:"40" Salary: "30000" Name:"Swaroop" Age:"22" Marks: "75" 它如何工作 為了使用繼承,我們把基本類的名稱作為一個元組跟在定義類時的類名稱之后。然后,我們注意 到基本類的__init__方法專門使用self變量調用,這樣我們就可以初始化對象的基本類部分。這一 點十分重要——Python不會自動調用基本類的constructor,你得親自專門調用它。 我們還觀察到我們在方法調用之前加上類名稱前綴,然后把self變量及其他參數傳遞給它。 注意,在我們使用SchoolMember類的tell方法的時候,我們把Teacher和Student的實例僅僅作為 SchoolMember的實例。 另外,在這個例子中,我們調用了子類型的tell方法,而不是SchoolMember類的tell方法。可以這 樣來理解,Python總是首先查找對應類型的方法,在這個例子中就是如此。如果它不能在導出類 中找到對應的方法,它才開始到基本類中逐個查找。基本類是在類定義的時候,在元組之中指明 的。 一個朮語的注釋——如果在繼承元組中列了一個以上的類,那麼它就被稱作 多重繼承 。 上一頁 上一級 下一頁 類與對象的變量 首頁 概括 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch11s07.html(第 3/3 頁)2010-10-3 18:09:55 簡明 Python 教程 / 面向對象的編程 / 概括 簡明 Python 教程 第11章 面向對象的編程 上一頁 概括 下一頁 概括 我們已經研究了類和對象的多個內容以及與它們相關的多個朮語。通過本章,你已經了解了面向 對象的編程的優點和缺陷。Python是一個高度面向對象的語言,理解這些概念會在將來有助于你 進一步深入學習Python。 接下來,我們將學習如何處理輸入/輸出已經如何用Python訪問文件。 上一頁 上一級 下一頁 繼承 首頁 第12章 輸入/輸出 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch11s08.html2010-10-3 18:09:58 簡明 Python 教程 / 輸入/輸出 / 文件 簡明 Python 教程 第12章 輸入/輸出 上一頁 文件 下一頁 第12章 輸入/輸出 目錄表 文件 使用文件 儲存器 儲存與取儲存 概括 在很多時候,你會想要讓你的程序與用戶(可能是你自己)交互。你會從用戶那里得到輸入,然 后打印一些結果。我們可以分別使用raw_input和print語句來完成這些功能。對于輸出,你也可以 使用多種多樣的str(字符串)類。例如,你能夠使用rjust方法來得到一個按一定寬度右對齊的字 符串。利用help(str)獲得更多詳情。 另一個常用的輸入/輸出類型是處理文件。創建、讀和寫文件的能力是許多程序所必需的,我們 將會在這章探索如何實現這些功能。 文件 你可以通過創建一個file類的對象來打開一個文件,分別使用file類的read、readline或write方法來恰 當地讀寫文件。對文件的讀寫能力依賴于你在打開文件時指定的模式。最后,當你完成對文件的 操作的時候,你調用close方法來告訴Python我們完成了對文件的使用。 使用文件 例12.1 使用文件 #!/usr/bin/python # Filename: using_file.py poem = '''\ Programming is fun When the work is done http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch12.html(第 1/3 頁)2010-10-3 18:10:02 簡明 Python 教程 / 輸入/輸出 / 文件 if you wanna make your work also fun: use Python! ''' f = file('poem.txt', 'w') # open for 'w'riting f.write(poem) # write text to file f.close() # close the file f = file('poem.txt') # if no mode is specified, 'r'ead mode is assumed by default while True: line = f.readline() if len(line) == 0: # Zero length indicates EOF break print line, # Notice comma to avoid automatic newline added by Python f.close() # close the file (源文件:code/using_file.py) 輸出 $ python using_file.py Programming is fun When the work is done if you wanna make your work also fun: use Python! 它如何工作 首先,我們通過指明我們希望打開的文件和模式來創建一個file類的實例。模式可以為讀模式 ('r')、寫模式('w')或追加模式('a')。事實上還有多得多的模式可以使用,你可以使用help (file)來了解它們的詳情。 我們首先用寫模式打開文件,然后使用file類的write方法來寫文件,最后我們用close關閉這個文 件。 接下來,我們再一次打開同一個文件來讀文件。如果我們沒有指定模式,讀模式會作為默認的模 式。在一個循環中,我們使用readline方法讀文件的每一行。這個方法返回包括行末換行符的一個 完整行。所以,當一個 空的 字符串被返回的時候,即表示文件末已經到達了,于是我們停止循 環。 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch12.html(第 2/3 頁)2010-10-3 18:10:02 簡明 Python 教程 / 輸入/輸出 / 文件 注意,因為從文件讀到的內容已經以換行符結尾,所以我們在print語句上使用逗號來消除自動換 行。最后,我們用close關閉這個文件。 現在,來看一下poem.txt文件的內容來驗証程序確實工作正常了。 上一頁 上一級 下一頁 概括 首頁 儲存器 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch12.html(第 3/3 頁)2010-10-3 18:10:02 簡明 Python 教程 / 輸入/輸出 / 儲存器 簡明 Python 教程 第12章 輸入/輸出 上一頁 儲存器 下一頁 儲存器 Python提供一個標准的模塊,稱為pickle。使用它你可以在一個文件中儲存任何Python對象,之后 你又可以把它完整無缺地取出來。這被稱為 持久地 儲存對象。 還有另一個模塊稱為cPickle,它的功能和pickle模塊完全相同,只不過它是用C語言編寫的,因此 要快得多(比pickle快1000倍)。你可以使用它們中的任一個,而我們在這里將使用cPickle模塊。 記住,我們把這兩個模塊都簡稱為pickle模塊。 儲存與取儲存 例12.2 儲存與取儲存 #!/usr/bin/python # Filename: pickling.py import cPickle as p #import pickle as p shoplistfile = 'shoplist.data' # the name of the file where we will store the object shoplist = ['apple', 'mango', 'carrot'] # Write to the file f = file(shoplistfile, 'w') p.dump(shoplist, f) # dump the object to a file f.close() del shoplist # remove the shoplist # Read back from the storage f = file(shoplistfile) storedlist = p.load(f) print storedlist http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch12s02.html(第 1/2 頁)2010-10-3 18:10:05 簡明 Python 教程 / 輸入/輸出 / 儲存器 (源文件:code/pickling.py) 輸出 $ python pickling.py ['apple', 'mango', 'carrot'] 它如何工作 首先,請注意我們使用了import..as語法。這是一種便利方法,以便于我們可以使用更短的模塊名 稱。在這個例子中,它還讓我們能夠通過簡單地改變一行就切換到另一個模塊(cPickle或者 pickle)!在程序的其余部分的時候,我們簡單地把這個模塊稱為p。 為了在文件里儲存一個對象,首先以寫模式打開一個file對象,然后調用儲存器模塊的dump函 數,把對象儲存到打開的文件中。這個過程稱為 儲存 。 接下來,我們使用pickle模塊的load函數的返回來取回對象。這個過程稱為 取儲存 。 上一頁 上一級 下一頁 文件 首頁 概括 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch12s02.html(第 2/2 頁)2010-10-3 18:10:05 簡明 Python 教程 / 輸入/輸出 / 概括 簡明 Python 教程 第12章 輸入/輸出 上一頁 概括 下一頁 概括 我們已經討論了多種類型的輸入/輸出,及文件處理和使用儲存器模塊。 接下來,我們將探索異常的概念。 上一頁 上一級 下一頁 儲存器 首頁 第13章 異常 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch12s03.html2010-10-3 18:10:09 簡明 Python 教程 / 異常 / 錯誤 簡明 Python 教程 第13章 異常 上一頁 錯誤 下一頁 第13章 異常 目錄表 錯誤 try..except 處理異常 引發異常 如何引發異常 try..finally 使用finally 概括 當你的程序中出現某些 異常的 狀況的時候,異常就發生了。例如,當你想要讀某個文件的時 候,而那個文件不存在。或者在程序運行的時候,你不小心把它刪除了。上述這些情況可以使用 異常來處理。 假如你的程序中有一些無效的語句,會怎麼樣呢?Python會引發并告訴你那里有一個錯誤,從而 處理這樣的情況。 錯誤 考慮一個簡單的print語句。假如我們把print誤拼為Print,注意大寫,這樣Python會 引發 一個語法 錯誤。 >>> Print 'Hello World' File "", line 1 Print 'Hello World' ^ SyntaxError: invalid syntax >>> print 'Hello World' Hello World http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13.html(第 1/2 頁)2010-10-3 18:10:12 簡明 Python 教程 / 異常 / 錯誤 我們可以觀察到有一個SyntaxError被引發,并且檢測到的錯誤位置也被打印了出來。這是這個錯 誤的 錯誤處理器 所做的工作。 上一頁 上一級 下一頁 概括 首頁 try..except http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13.html(第 2/2 頁)2010-10-3 18:10:12 簡明 Python 教程 / 異常 / try..except 簡明 Python 教程 第13章 異常 上一頁 try..except 下一頁 try..except 我們嘗試讀取用戶的一段輸入。按Ctrl-d,看一下會發生什麼。 >>> s = raw_input('Enter something --> ') Enter something --> Traceback (most recent call last): File "", line 1, in ? EOFError Python引發了一個稱為EOFError的錯誤,這個錯誤基本上意味著它發現一個不期望的 文件尾 (由 Ctrl-d表示) 接下來,我們將學習如何處理這樣的錯誤。 處理異常 我們可以使用try..except語句來處理異常。我們把通常的語句放在try-塊中,而把我們的錯誤處理 語句放在except-塊中。 例13.1 處理異常 #!/usr/bin/python # Filename: try_except.py import sys try: s = raw_input('Enter something --> ') except EOFError: print '\nWhy did you do an EOF on me?' sys.exit() # exit the program except: print '\nSome error/exception occurred.' # here, we are not exiting the program http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13s02.html(第 1/2 頁)2010-10-3 18:10:24 簡明 Python 教程 / 異常 / try..except print 'Done' (源文件:code/try_except.py) 輸出 $ python try_except.py Enter something --> Why did you do an EOF on me? $ python try_except.py Enter something --> Python is exceptional! Done 它如何工作 我們把所有可能引發錯誤的語句放在try塊中,然后在except從句/塊中處理所有的錯誤和異常。 except從句可以專門處理單一的錯誤或異常,或者一組包括在圓括號內的錯誤/異常。如果沒有給 出錯誤或異常的名稱,它會處理 所有的 錯誤和異常。對于每個try從句,至少都有一個相關聯的 except從句。 如果某個錯誤或異常沒有被處理,默認的Python處理器就會被調用。它會終止程序的運行,并且 打印一個消息,我們已經看到了這樣的處理。 你還可以讓try..catch塊關聯上一個else從句。當沒有異常發生的時候,else從句將被執行。 我們還可以得到異常對象,從而獲取更多有個這個異常的信息。這會在下一個例子中說明。 上一頁 上一級 下一頁 錯誤 首頁 引發異常 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13s02.html(第 2/2 頁)2010-10-3 18:10:24 簡明 Python 教程 / 異常 / 引發異常 簡明 Python 教程 第13章 異常 上一頁 引發異常 下一頁 引發異常 你可以使用raise語句 引發 異常。你還得指明錯誤/異常的名稱和伴隨異常 觸發的 異常對象。你可 以引發的錯誤或異常應該分別是一個Error或Exception類的直接或間接導出類。 如何引發異常 例13.2 如何引發異常 #!/usr/bin/python # Filename: raising.py class ShortInputException(Exception): '''A user-defined exception class.''' def __init__(self, length, atleast): Exception.__init__(self) self.length = length self.atleast = atleast try: s = raw_input('Enter something --> ') if len(s) < 3: raise ShortInputException(len(s), 3) # Other work can continue as usual here except EOFError: print '\nWhy did you do an EOF on me?' except ShortInputException, x: print 'ShortInputException: The input was of length %d, \ was expecting at least %d' % (x.length, x.atleast) else: print 'No exception was raised.' 源文件(code/raising.py) 輸出 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13s03.html(第 1/2 頁)2010-10-3 18:10:27 簡明 Python 教程 / 異常 / 引發異常 $ python raising.py Enter something --> Why did you do an EOF on me? $ python raising.py Enter something --> ab ShortInputException: The input was of length 2, was expecting at least 3 $ python raising.py Enter something --> abc No exception was raised. 它如何工作 這里,我們創建了我們自己的異常類型,其實我們可以使用任何預定義的異常/錯誤。這個新的 異常類型是ShortInputException類。它有兩個域——length是給定輸入的長度,atleast則是程序期望 的最小長度。 在except從句中,我們提供了錯誤類和用來表示錯誤/異常對象的變量。這與函數調用中的形參和 實參概念類似。在這個特別的except從句中,我們使用異常對象的length和atleast域來為用戶打印 一個恰當的消息。 上一頁 上一級 下一頁 try..except 首頁 try..finally http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13s03.html(第 2/2 頁)2010-10-3 18:10:27 簡明 Python 教程 / 異常 / try..finally 簡明 Python 教程 第13章 異常 上一頁 try..finally 下一頁 try..finally 假如你在讀一個文件的時候,希望在無論異常發生與否的情況下都關閉文件,該怎麼做呢?這可 以使用finally塊來完成。注意,在一個try塊下,你可以同時使用except從句和finally塊。如果你要 同時使用它們的話,需要把一個嵌入另外一個。 使用finally 例13.3 使用finally #!/usr/bin/python # Filename: finally.py import time try: f = file('poem.txt') while True: # our usual file-reading idiom line = f.readline() if len(line) == 0: break time.sleep(2) print line, finally: f.close() print 'Cleaning up...closed the file' (源文件:code/finally.py) 輸出 $ python finally.py Programming is fun When the work is done Cleaning up...closed the file http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13s04.html(第 1/2 頁)2010-10-3 18:10:33 簡明 Python 教程 / 異常 / try..finally Traceback (most recent call last): File "finally.py", line 12, in ? time.sleep(2) KeyboardInterrupt 它如何工作 我們進行通常的讀文件工作,但是我有意在每打印一行之前用time.sleep方法暫停2秒鐘。這樣做 的原因是讓程序運行得慢一些(Python由于其本質通常運行得很快)。在程序運行的時候,按 Ctrl-c中斷/取消程序。 我們可以觀察到KeyboardInterrupt異常被觸發,程序退出。但是在程序退出之前,finally從句仍然 被執行,把文件關閉 上一頁 上一級 下一頁 引發異常 首頁 概括 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13s04.html(第 2/2 頁)2010-10-3 18:10:33 簡明 Python 教程 / 異常 / 概括 簡明 Python 教程 第13章 異常 上一頁 簡介 下一頁 概括 我們已經討論了try..except和try..finally語句的用法。我們還學習了如何創建我們自己的異常類型和 如何引發異常。 接下來,我們將探索Python標准庫。 上一頁 上一級 下一頁 第14章 Python標准 try..finally 首頁 庫 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch13s05.html2010-10-3 18:10:40 簡明 Python 教程 / Python標准庫 / 簡介 簡明 Python 教程 第14章 Python標准庫 上一頁 簡介 下一頁 第14章 Python標准庫 目錄表 簡介 sys模塊 命令行參數 更多sys的內容 os模塊 概括 簡介 Python標准庫是隨Python附帶安裝的,它包含大量極其有用的模塊。熟悉Python標准庫是十分重 要的,因為如果你熟悉這些庫中的模塊,那麼你的大多數問題都可以簡單快捷地使用它們來解 決。 我們已經研究了一些這個庫中的常用模塊。你可以在Python附帶安裝的文檔的“庫參考”一節中 了解Python標准庫中所有模塊的完整內容。 上一頁 上一級 下一頁 概括 首頁 sys模塊 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch14.html2010-10-3 18:10:45 簡明 Python 教程 / Python標准庫 / sys模塊 簡明 Python 教程 第14章 Python標准庫 上一頁 sys模塊 下一頁 sys模塊 sys模塊包含系統對應的功能。我們已經學習了sys.argv列表,它包含命令行參數。 命令行參數 例14.1 使用sys.argv #!/usr/bin/python # Filename: cat.py import sys def readfile(filename): '''Print a file to the standard output.''' f = file(filename) while True: line = f.readline() if len(line) == 0: break print line, # notice comma f.close() # Script starts from here if len(sys.argv) < 2: print 'No action specified.' sys.exit() if sys.argv[1].startswith('--'): option = sys.argv[1][2:] # fetch sys.argv[1] but without the first two characters if option == 'version': print 'Version 1.2' elif option == 'help': print '''\ This program prints files to the standard output. http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch14s02.html(第 1/3 頁)2010-10-3 18:10:48 簡明 Python 教程 / Python標准庫 / sys模塊 Any number of files can be specified. Options include: --version : Prints the version number --help : Display this help''' else: print 'Unknown option.' sys.exit() else: for filename in sys.argv[1:]: readfile(filename) (源文件:code/cat.py) 輸出 $ python cat.py No action specified. $ python cat.py --help This program prints files to the standard output. Any number of files can be specified. Options include: --version : Prints the version number --help : Display this help $ python cat.py --version Version 1.2 $ python cat.py --nonsense Unknown option. $ python cat.py poem.txt Programming is fun When the work is done if you wanna make your work also fun: use Python! 它如何工作 這個程序用來模范Linux/Unix用戶熟悉的cat命令。你只需要指明某些文本文件的名字,這個程序 會把它們打印輸出。 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch14s02.html(第 2/3 頁)2010-10-3 18:10:48 簡明 Python 教程 / Python標准庫 / sys模塊 在Python程序運行的時候,即不是在交互模式下,在sys.argv列表中總是至少有一個項目。它就是 當前運行的程序名稱,作為sys.argv[0](由于Python從0開始計數)。其他的命令行參數在這個項 目之后。 為了使這個程序對用戶更加友好,我們提供了一些用戶可以指定的選項來了解更多程序的內容。 我們使用第一個參數來檢驗我們的程序是否被指定了選項。如果使用了--version選項,程序的版 本號將被打印出來。類似地,如果指定了--help選項,我們提供一些關于程序的解釋。我們使用 sys.exit函數退出正在運行的程序。和以往一樣,你可以看一下help(sys.exit)來了解更多詳情。 如果沒有指定任何選項,而是為程序提供文件名的話,它就簡單地打印出每個文件地每一行,按 照命令行中的順序一個文件接著一個文件地打印。 順便說一下,名稱cat是 concatenate 的縮寫,它基本上表明了程序的功能——它可以在輸出打印一 個文件或者把兩個或兩個以上文件連接/級連在一起打印。 更多sys的內容 sys.version字符串給你提供安裝的Python的版本信息。sys.version_info元組則提供一個更簡單的方法 來使你的程序具備Python版本要求功能。 [swaroop@localhost code]$ python >>> import sys >>> sys.version '2.3.4 (#1, Oct 26 2004, 16:42:40) \n[GCC 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)]' >>> sys.version_info (2, 3, 4, 'final', 0) 對于有經驗的程序員,sys模塊中其他令人感興趣的項目有sys.stdin、sys.stdout和sys.stderr它們分別 對應你的程序的標准輸入、標准輸出和標准錯誤流。 上一頁 上一級 下一頁 簡介 首頁 os模塊 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch14s02.html(第 3/3 頁)2010-10-3 18:10:48 簡明 Python 教程 / Python標准庫 / os模塊 簡明 Python 教程 第14章 Python標准庫 上一頁 os模塊 下一頁 os模塊 這個模塊包含普遍的操作系統功能。如果你希望你的程序能夠與平台無關的話,這個模塊是尤為 重要的。即它允許一個程序在編寫后不需要任何改動,也不會發生任何問題,就可以在Linux和 Windows下運行。一個例子就是使用os.sep可以取代操作系統特定的路徑分割符。 下面列出了一些在os模塊中比較有用的部分。它們中的大多數都簡單明了。 ● os.name字符串指示你正在使用的平台。比如對于Windows,它是'nt',而對于Linux/Unix用 戶,它是'posix'。 ● os.getcwd()函數得到當前工作目錄,即當前Python腳本工作的目錄路徑。 ● os.getenv()和os.putenv()函數分別用來讀取和設置環境變量。 ● os.listdir()返回指定目錄下的所有文件和目錄名。 ● os.remove()函數用來刪除一個文件。 ● os.system()函數用來運行shell命令。 ● os.linesep字符串給出當前平台使用的行終止符。例如,Windows使用'\r\n',Linux使用'\n'而 Mac使用'\r'。 ● os.path.split()函數返回一個路徑的目錄名和文件名。 >>> os.path.split('/home/swaroop/byte/code/poem.txt') ('/home/swaroop/byte/code', 'poem.txt') ● os.path.isfile()和os.path.isdir()函數分別檢驗給出的路徑是一個文件還是目錄。類似地,os. path.existe()函數用來檢驗給出的路徑是否真地存在。 你可以利用Python標准文檔去探索更多有關這些函數和變量的詳細知識。你也可以使用help(sys) 等等。 上一頁 上一級 下一頁 sys模塊 首頁 概括 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch14s03.html2010-10-3 18:10:51 簡明 Python 教程 / Python標准庫 / 概括 簡明 Python 教程 第14章 Python標准庫 上一頁 概括 下一頁 概括 我們已經學習了Python標准庫中的sys模塊和os模塊的一部分功能。你應該利用Python標准文檔去 學習這兩個模塊以及其他模塊的更多內容。 接下來,我們將要學習Python中剩余的几個方面的內容,從而使我們的Python課程更加 完整 。 上一頁 上一級 下一頁 第15章 更多Python os模塊 首頁 的內容 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch14s04.html2010-10-3 18:10:53 簡明 Python 教程 / 更多Python的內容 / 特殊的方法 簡明 Python 教程 第15章 更多Python的內容 上一頁 特殊的方法 下一頁 第15章 更多Python的內容 目錄表 特殊的方法 單語句塊 列表綜合 使用列表綜合 在函數中接收元組和列表 lambda形式 使用lambda形式 exec和eval語句 assert語句 repr函數 概括 到目前為止,我們已經學習了絕大多數常用的Python知識。在這一章中,我們將要學習另外一些 方面的Python知識,從而使我們對Python的了解更加 完整 。 特殊的方法 在類中有一些特殊的方法具有特殊的意義,比如__init__和__del__方法,它們的重要性我們已經 學習過了。 一般說來,特殊的方法都被用來模仿某個行為。例如,如果你想要為你的類使用x[key]這樣的索 引操作(就像列表和元組一樣),那麼你只需要實現__getitem__()方法就可以了。想一下, Python就是對list類這樣做的! 下面這個表中列出了一些有用的特殊方法。如果你想要知道所有的特殊方法,你可以在《Python 參考手冊》中找到一個龐大的列表。 表15.1 一些特殊的方法 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15.html(第 1/2 頁)2010-10-3 18:10:56 簡明 Python 教程 / 更多Python的內容 / 特殊的方法 名稱 說明 __init__(self,...) 這個方法在新建對象恰好要被返回使用之前被調用。 __del__(self) 恰好在對象要被刪除之前調用。 __str__(self) 在我們對對象使用print語句或是使用str()的時候調用。 當使用 小于 運算符(<)的時候調用。類似地,對于所有的運算符 __lt__(self,other) (+,>等等)都有特殊的方法。 __getitem__(self, 使用x[key]索引操作符的時候調用。 key) __len__(self) 對序列對象使用內建的len()函數的時候調用。 上一頁 上一級 下一頁 概括 首頁 單語句塊 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15.html(第 2/2 頁)2010-10-3 18:10:56 簡明 Python 教程 / 更多Python的內容 / 單語句塊 簡明 Python 教程 第15章 更多Python的內容 上一頁 單語句塊 下一頁 單語句塊 現在,你已經很深刻地理解了每一個語句塊是通過它的縮進層次與其它塊區分開來的。然而這在 大多數情況下是正確的,但是并非100%的准確。如果你的語句塊只包含一句語句,那麼你可以 在條件語句或循環語句的同一行指明它。下面這個例子清晰地說明了這一點: >>> flag = True >>> if flag: print 'Yes' ... Yes 就如你所看見的,單個語句被直接使用而不是作為一個獨立的塊使用。雖然這樣做可以使你的程 序變得 小一些 ,但是除了檢驗錯誤之外我強烈建議你不要使用這種縮略方法。不使用它的一個 主要的理由是一旦你使用了恰當的縮進,你就可以很方便地添加一個額外的語句。 另外,注意在使用交互模式的Python解釋器的時候,它會通過恰當地改變提示符來幫助你輸入語 句。在上面這個例子中,當你輸入了關鍵字if之后,Python解釋器把提示符改變為...以表示語句還 沒有結束。在這種情況下,我們按回車鍵用來確認語句已經完整了。然后,Python完成整個語句 的執行,并且返回原來的提示符并且等待下一句輸入。 上一頁 上一級 下一頁 特殊的方法 首頁 列表綜合 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s02.html2010-10-3 18:10:59 簡明 Python 教程 / 更多Python的內容 / 列表綜合 簡明 Python 教程 第15章 更多Python的內容 上一頁 列表綜合 下一頁 列表綜合 通過列表綜合,可以從一個已有的列表導出一個新的列表。例如,你有一個數的列表,而你想要 得到一個對應的列表,使其中所有大于2的數都是原來的2倍。對于這種應用,列表綜合是最理想 的方法。 使用列表綜合 例15.1 使用列表綜合 #!/usr/bin/python # Filename: list_comprehension.py listone = [2, 3, 4] listtwo = [2*i for i in listone if i > 2] print listtwo (源文件:code/list_comprehension.py) 輸出 $ python list_comprehension.py [6, 8] 它如何工作 這里我們為滿足條件(if i > 2)的數指定了一個操作(2*i),從而導出一個新的列表。注意原來 的列表并沒有發生變化。在很多時候,我們都是使用循環來處理列表中的每一個元素,而使用列 表綜合可以用一種更加精確、簡潔、清楚的方法完成相同的工作。 上一頁 上一級 下一頁 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s03.html(第 1/2 頁)2010-10-3 18:11:03 簡明 Python 教程 / 更多Python的內容 / 列表綜合 在函數中接收元組 單語句塊 首頁 和列表 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s03.html(第 2/2 頁)2010-10-3 18:11:03 簡明 Python 教程 / 更多Python的內容 / 在函數中接收元組和列表 簡明 Python 教程 第15章 更多Python的內容 上一頁 在函數中接收元組和列表 下一頁 在函數中接收元組和列表 當要使函數接收元組或字典形式的參數的時候,有一種特殊的方法,它分別使用*和**前綴。這種 方法在函數需要獲取可變數量的參數的時候特別有用。 >>> def powersum(power, *args): ... '''Return the sum of each argument raised to specified power.''' ... total = 0 ... for i in args: ... total += pow(i, power) ... return total ... >>> powersum(2, 3, 4) 25 >>> powersum(2, 10) 100 由于在args變量前有*前綴,所有多余的函數參數都會作為一個元組存儲在args中。如果使用的是 **前綴,多余的參數則會被認為是一個字典的鍵/值對。 上一頁 上一級 下一頁 列表綜合 首頁 lambda形式 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s04.html2010-10-3 18:11:11 簡明 Python 教程 / 更多Python的內容 / lambda形式 簡明 Python 教程 第15章 更多Python的內容 上一頁 lambda形式 下一頁 lambda形式 lambda語句被用來創建新的函數對象,并且在運行時返回它們。 例15.2 使用lambda形式 #!/usr/bin/python # Filename: lambda.py def make_repeater(n): return lambda s: s*n twice = make_repeater(2) print twice('word') print twice(5) (源文件:code/lambda.py) 輸出 $ python lambda.py wordword 10 它如何工作 這里,我們使用了make_repeater函數在運行時創建新的函數對象,并且返回它。lambda語句用來 創建函數對象。本質上,lambda需要一個參數,后面僅跟單個表達式作為函數體,而表達式的值 被這個新建的函數返回。注意,即便是print語句也不能用在lambda形式中,只能使用表達式。 上一頁 上一級 下一頁 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s05.html(第 1/2 頁)2010-10-3 18:11:13 簡明 Python 教程 / 更多Python的內容 / lambda形式 在函數中接收元組 首頁 exec和eval語句 和列表 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s05.html(第 2/2 頁)2010-10-3 18:11:13 簡明 Python 教程 / 更多Python的內容 / exec和eval語句 簡明 Python 教程 第15章 更多Python的內容 上一頁 exec和eval語句 下一頁 exec和eval語句 exec語句用來執行儲存在字符串或文件中的Python語句。例如,我們可以在運行時生成一個包含 Python代碼的字符串,然后使用exec語句執行這些語句。下面是一個簡單的例子。 >>> exec 'print "Hello World"' Hello World eval語句用來計算存儲在字符串中的有效Python表達式。下面是一個簡單的例子。 >>> eval('2*3') 6 上一頁 上一級 下一頁 lambda形式 首頁 assert語句 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s06.html2010-10-3 18:11:18 簡明 Python 教程 / 更多Python的內容 / assert語句 簡明 Python 教程 第15章 更多Python的內容 上一頁 assert語句 下一頁 assert語句 assert語句用來聲明某個條件是真的。例如,如果你非常確信某個你使用的列表中至少有一個元 素,而你想要檢驗這一點,并且在它非真的時候引發一個錯誤,那麼assert語句是應用在這種情形 下的理想語句。當assert語句失敗的時候,會引發一個AssertionError。 >>> mylist = ['item'] >>> assert len(mylist) >= 1 >>> mylist.pop() 'item' >>> assert len(mylist) >= 1 Traceback (most recent call last): File "", line 1, in ? AssertionError 上一頁 上一級 下一頁 exec和eval語句 首頁 repr函數 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s07.html2010-10-3 18:11:22 簡明 Python 教程 / 更多Python的內容 / repr函數 簡明 Python 教程 第15章 更多Python的內容 上一頁 repr函數 下一頁 repr函數 repr函數用來取得對象的規范字符串表示。反引號(也稱轉換符)可以完成相同的功能。注意, 在大多數時候有eval(repr(object)) == object。 >>> i = [] >>> i.append('item') >>> `i` "['item']" >>> repr(i) "['item']" 基本上,repr函數和反引號用來獲取對象的可打印的表示形式。你可以通過定義類的__repr__方法 來控制你的對象在被repr函數調用的時候返回的內容。 上一頁 上一級 下一頁 assert語句 首頁 概括 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s08.html2010-10-3 18:11:24 簡明 Python 教程 / 更多Python的內容 / 概括 簡明 Python 教程 第15章 更多Python的內容 上一頁 概括 下一頁 概括 在這一章中,我們又學習了一些Python的特色,然而你可以肯定我們并沒有學習完Python的所有 特色。不過,到目前為止,我們確實已經學習了絕大多數你在實際中會使用的內容。這些已經足 以讓你去創建任何程序了。 接下來,我們會討論一下如何進一步深入探索Python。 上一頁 上一級 下一頁 第16章 接下來學習 repr函數 首頁 什麼? http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch15s09.html2010-10-3 18:11:27 簡明 Python 教程 / 接下來學習什麼? / 圖形軟件 簡明 Python 教程 第16章 接下來學習什麼? 上一頁 圖形軟件 下一頁 第16章 接下來學習什麼? 目錄表 圖形軟件 GUI工具概括 探索更多內容 概括 如果你已經完全讀完了這本書并且也實踐著編寫了很多程序,那麼你一定已經能夠非常熟練自如 地使用Python了。你可能也已經編寫了一些Python程序來嘗試練習各種Python技能和特性。如果 你還沒有那樣做的話,那麼你一定要快點去實踐。現在的問題是“接下來學習什麼?”。 我會建議你先解決這樣一個問題:創建你自己的命令行 地址簿 程序。在這個程序中,你可以添 加、修改、刪除和搜索你的聯系人(朋友、家人和同事等等)以及它們的信息(諸如電子郵件地 址和/或電話號碼)。這些詳細信息應該被保存下來以便以后提取。 思考一下我們到目前為止所學的各種東西的話,你會覺得這個問題其實相當簡單。如果你仍然希 望知道該從何處入手的話,那麼這里也有一個提示。 提示(其實你不應該閱讀這個提示) 創建一個類來表示一個人的信息。使用字典儲存每個人的對 象,把他們的名字作為鍵。使用cPickle模塊永久地把這些對象儲存在你的硬盤上。使用字典內建 的方法添加、刪除和修改人員信息。 一旦你完成了這個程序,你就可以說是一個Python程序員了。現在,請立即寄一封信給我感謝我 為你提供了這本優秀的教材吧。是否告知我,如你所愿,但是我確實希望你能夠告訴我。 這里有一些繼續你的Python之路的方法: 圖形軟件 使用Python的GUI庫——你需要使用這些庫來用Python語言創建你自己的圖形程序。使用GUI庫和 它們的Python綁定,你可以創建你自己的IrfanView、Kuickshow軟件或者任何別的類似的東西。綁 定讓你能夠使用Python語言編寫程序,而使用的庫本身是用C、C++或者別的語言編寫的。 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch16.html(第 1/2 頁)2010-10-3 18:11:30 簡明 Python 教程 / 接下來學習什麼? / 圖形軟件 有許多可供選擇的使用Python的GUI: ● PyQt 這是Qt工具包的Python綁定。Qt工具包是構建KDE的基石。Qt,特別是配合Qt Designer和出色的Qt文檔之后,它極其易用并且功能非常強大。你可以在Linux下免費使用 它,但是如果你在Windows下使用它需要付費。使用PyQt,你可以在Linux/Unix上開發免費 的(GPL約定的)軟件,而開發具產權的軟件則需要付費。一個很好的PyQt資源是《使用 Python語言的GUI編程:Qt版》請查閱官方主頁以獲取更多詳情。 ● PyGTK 這是GTK+工具包的Python綁定。GTK+工具包是構建GNOME的基石。GTK+在使 用上有很多怪癖的地方,不過一旦你習慣了,你可以非常快速地開發GUI應用程序。Glade 圖形界面設計器是必不可少的,而文檔還有待改善。GTK+在Linux上工作得很好,而它的 Windows接口還不完整。你可以使用GTK+開發免費和具有產權的軟件。請查閱官方主頁以 獲取更多詳情。 ● wxPython 這是wxWidgets工具包的Python綁定。wxPython有與它相關的學習方法。它的可移 植性極佳,可以在Linux、Windows、Mac甚至嵌入式平台上運行。有很多wxPython的IDE, 其中包括GUI設計器以及如SPE(Santi's Python Editor)和wxGlade那樣的GUI開發器。你可 以使用wxPython開發免費和具有產權的軟件。請查閱官方主頁以獲取更多詳情。 ● TkInter 這是現存最老的GUI工具包之一。如果你使用過IDLE,它就是一個TkInter程序。在 PythonWare.org上的TkInter文檔是十分透徹的。TkInter具備可移植性,可以在Linux/Unix和 Windows下工作。重要的是,TkInter是標准Python發行版的一部分。 ● 要獲取更多選擇,請參閱Python.org上的GUI編程wiki頁。 GUI工具概括 不幸的是,并沒有單一的標准Python GUI工具。我建議你根據你的情況在上述工具中選擇一個。 首要考慮的因素是你是否愿意為GUI工具付費。其次考慮的是你是想讓你的程序運行在Linux下、 Windows下還是兩者都要。第三個考慮因素根據你是Linux下的KDE用戶還是GNOME用戶而定。 未來的章節 我打算為本書編寫一或兩個關于GUI編程的章節。我可能會選擇wxPython作為工具包。如果你想 要表達你對這個主題的意見,請加入byte-of-python郵件列表。在這個郵件列表中,讀者會與我討 論如何改進本書。 上一頁 上一級 下一頁 概括 首頁 探索更多內容 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch16.html(第 2/2 頁)2010-10-3 18:11:30 簡明 Python 教程 / 接下來學習什麼? / 探索更多內容 簡明 Python 教程 第16章 接下來學習什麼? 上一頁 探索更多內容 下一頁 探索更多內容 ● Python標准庫是一個丰富的庫,在大多數時候,你可以在這個庫中找到你所需的東西。這 被稱為Python的“功能齊全”理念。我強烈建議你在開始開發大型Python程序之前瀏覽一 下Python標准文檔。 ● Python.org——Python編程語言的官方主頁。你可以在上面找到Python語言和解釋器的最新 版本。另外還有各種郵件列表活躍地討論Python的各方面內容。 ● comp.lang.python是討論Python語言的世界性新聞組。你可以把你的疑惑和詢問貼在這個新 聞組上。可以使用Google群在線訪問這個新聞組,或加入作為新聞組鏡像的郵件列表。 ● 《Python實用大全》是一個極有價值的秘訣和技巧集合,它幫助你解決某些使用Python的 問題。這是每個Python用戶必讀的一本書。 ● 《迷人的Python》是David Mertz編著的一系列優秀的Python相關文章。 ● 《深入理解Python》是給有經驗的Python程序員的一本很優秀的書。如果你已經完整地閱 讀了本書,那麼我強烈建議你接下來閱讀《深入理解Python》。它覆蓋了包括XML處理、 單元測試和功能性編程在內的廣泛的主題。 ● Jython是用Java語言實現的Python解釋器。這意味著你可以用Python語言編寫程序而同時使 用Java庫!Jython是一個穩定成熟的軟件。如果你也是一個Java程序員,我強烈建議你嘗試 一下Jython。 ● IronPython是用C#語言實現的Python解釋器,可以運行在.NET、Mono和DotGNU平台上。 這意味著你可以用Python語言編寫程序而使用.NET庫以及其他由這三種平台提供的庫! IronPython還只是一個前期alpha測試軟件,現在還只適合用來進行試驗。Jim Hugunin, IronPython的開發者,已經加入了微軟公司,將在將來全力開發一個完整版本的 IronPython。 ● Lython是Python語言的Lisp前段。它類似于普通的Lisp語言,會被直接編譯為Python字節 碼,這意味著它能與我們普通的Python代碼協同工作。 ● 另外還有很多很多的Python資源。其中比較有趣的有Daily Python-URL!,它使你保持與 Python的最新進展同步。另外還有Vaults of Parnassus、ONLamp.com Python DevCenter、 dirtSimple.org、Python Notes等等。 上一頁 上一級 下一頁 圖形軟件 首頁 概括 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch16s02.html2010-10-3 18:11:33 簡明 Python 教程 / 接下來學習什麼? / 概括 簡明 Python 教程 第16章 接下來學習什麼? 上一頁 概括 下一頁 概括 現在,我們已經來到了本書的末尾,但是就如那句名言,這只是 開始的結束 !你現在是一個滿 懷渴望的Python用戶,毫無疑問你准備用Python解決許多問題。你可以使你的計算機自動地完成 許多先前無法想象的工作或者編寫你自己的游戲,以及更多別的什麼東西。所以,請出發吧! 上一頁 上一級 下一頁 附錄A 自由/開放 探索更多內容 首頁 源碼軟件 (FLOSS) http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/ch16s03.html2010-10-3 18:11:36 簡明 Python 教程 / 自由/開放源碼軟件(FLOSS) 簡明 Python 教程 附錄A 自由/開放源碼軟件(FLOSS) 上一頁 下一頁 附錄A 自由/開放源碼軟件(FLOSS) FLOSS基于社區的概念,而它本身基于共享,特別是知識共享的概念。FLOSS可以免費使用、修 改和再發行。 如果你已經讀了本書,那麼你一定熟悉FLOSS,因為你一直在使用Python! 如果你想要了解更多的FLOSS,你可以探索下面這個列表中的軟件。我列出了一些最著名的 FLOSS以及那些可以跨平台(即在Linux、Windows等)工作的FLOSS。這樣你無需馬上切換到 Linux就可以嘗試使用這些軟件了, 盡管你最終一定會轉到Linux上的 。 ● Linux 這是一個正在慢慢被世界接納的FLOSS操作系統!它最初由Linus Torvalds在學生時候 開發。現在,它已經可以與微軟Windows相匹敵。最新的2.6版本核心,無論從速度、穩定 性還是擴展性角度來說,都是一個巨大的突破。【Linux核心】 ● Knoppix 這是一個僅僅在CD上運行的Linux發行版!它不需要安裝——你只需要重新啟動你 的計算機,把CD放入光驅,就可以開始使用一個完全的Linux發行版了!你可以使用所有 的隨標准Linux發行版發行的FLOSS,如運行Python程序、編譯C程序、看電影等等。然后 再次重啟你的計算機,取出CD,就可以使用你現有的操作系統了,就好像什麼都沒有發 生過一樣。【Knoppix】 ● Fedora 這是一個由社區開發維護的發行版,由Red Hat公司贊助。它是最流行的Linux發行 版之一。它包含Linux核心、KDE、GNOME和XFCE桌面以及眾多的FLOSS,而所有這些都 易于安裝、易于使用。 如果你擔心你是一個完全的Linux生手,那麼我推荐你嘗試Mandrake Linux。最新發布 Mandrake 10.1確實很棒。【Fedora Linux、Mandrake Linux】 ● OpenOffice.org 這是一個優秀的辦公套件,它基于Sun Microsystems的StarOffice軟件。 OpenOffice由文本編寫器、演講輔助、電子表格和繪圖組件等等組成。它甚至可以方便地 打開和編輯微軟Word和PowerPoint文件。它可以在几乎所有平台上運行。即將推出的 OpenOffice 2.0有一些重大的改進。【OpenOffice】 ● Mozilla Firefox 這是被認為可以在未來几年擊敗Internet Explorer(僅按照市場份額計算)的 下一代網絡瀏覽器。它極快,它的一些合理的、令人印象深刻的特性廣受好評。它的擴展 理念允許在它上面添加各種功能。 它的姐妹產品Thunderbird是一個優秀的電子郵件客戶端,使閱讀電子郵件變得十分快捷。 【Mozilla Firefox、Mozilla Thunderbird】 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apa.html(第 1/3 頁)2010-10-3 18:11:39 簡明 Python 教程 / 自由/開放源碼軟件(FLOSS) ● Mono 這是一個微軟.NET平台的開源實現。它使我們可以在Linux、Windows、FreeBSD、 Mac OS和許多其他平台上創建和運行.NET程序。Mono執行CLI和C#的ECMA標准,這個標 准已經由微軟、英特爾和惠普提交稱為一個開放標准。這也是邁向ISO標准的一步。 目前,Mono包含一個完整的C#主控制台(它本身也由C#編寫!)、一個具備完整特性的 ASP.NET實現、許多數據庫ADO.NET提供器另外還有每天不斷改善和增加的新特性。 【Mono、ECMA、Microsoft .NET】 ● Apache網絡服務器 這是最流行的開源網絡服務器。事實上,它是地球上最流行的網絡服務 器!它運行著几乎60%的網站。對——Apache處理的網站比它所有的競爭對手(包括微軟 IIS)之和還要多。【Apache】 ● MySQL 這是一個極其流行的開源數據庫服務器。它以它的快速最為著名。在它的最新版本 中又添加了更多的特性。【MySQL】 ● MPlayer 這是一個視頻播放器,可以播放DivX、MP3、Ogg、VCD、DVD……誰說開源軟 件就不能具有趣味呢?【MPlayer】 ● Movix 這是一個Linux發行版,它基于Knoppix僅僅在CD上運行用來播放電影!你可以創建 Movix的CD。它們是可啟動的CD,當你重啟計算機的時候,放入CD,電影就會自己開始 播放!使用Movix觀看電影,你甚至不需要硬盤。【Movix】 上面這個列表只是希望給你一個大概的印象——還有很多別的優秀FLOSS,比如Perl語言、PHP語 言、Drupal網站內容管理系統、PostgreSQL數據庫服務器、TORCS賽車游戲、KDevelop IDE、 Anjuta IDE、Xine——電影播放器、VIM編輯器、Quanta+編輯器、XMMS音頻播放器、GIMP圖像 編輯程序……這個列表可以一直繼續下去。 訪問下述網站以獲取更多FLOSS信息: ● SourceForge ● FreshMeat ● KDE ● GNOME 要獲知FLOSS世界的最新進展,請訪問下述網站: ● OSNews ● LinuxToday ● NewsForge ● SwaroopCH's blog 那麼,現在就出發去探索廣博、免費、開放的FLOSS世界了吧! http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apa.html(第 2/3 頁)2010-10-3 18:11:39 簡明 Python 教程 / 自由/開放源碼軟件(FLOSS) 上一頁 下一頁 概括 首頁 附錄B 關于本書 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apa.html(第 3/3 頁)2010-10-3 18:11:39 簡明 Python 教程 / 關于本書 / 后記 簡明 Python 教程 附錄B 關于本書 上一頁 后記 下一頁 附錄B 關于本書 目錄表 后記 關于作者 關于譯者 關于簡體中文譯本 后記 我在編寫本書時使用的几乎所有軟件都是 免費開放源碼的軟件 。在編寫本書的第一個草稿的時 候,我使用的是Red Hat 9.0 Linux,而現在第六次改寫的時候,使用的是Fedora Core 3 Linux。 最初,我使用KWord編寫本書(在前言的本書的由來中已經介紹了)。后來,我開始使用 DocBook XML和Kate,但是我發現這樣太乏味。所以,我開始使用OpenOffice,它對格式的控制 以及生成PDF的能力是很棒的。但是它生成的HTML過于龐大。最后,我發現了XEmacs,于是我 又開始重新使用DocBook XML來編寫本書,并且那時我打算把這個模式作為將來長期的方案。在 這個最新的第六次重寫時,我決定使用Quanta+來編輯。 我使用了標准的XSL樣式表,它隨Fedora Core 3 Linux附帶。另外,我也使用了標准的默認字體。 我編寫了一個CSS文件來為HTML頁增加顏色和樣式。同時,我還用Python語言編寫了一個粗劣 的詞匯分析器,它自動為書中所有的程序進行語法加亮。 上一頁 上一級 下一頁 附錄A 自由/開放 源碼軟件 首頁 關于作者 (FLOSS) http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apb.html2010-10-3 18:11:42 簡明 Python 教程 / 關于本書 / 關于作者 簡明 Python 教程 附錄B 關于本書 上一頁 關于作者 下一頁 關于作者 Swaroop C. H. 在Yahoo!駐印度班加羅爾的辦事處工作,他十分熱愛他的工作。他目前在技朮領域 的興趣有:包括Linux、DotGNU、Qt和MySQL在內的FLOSS、Python和C#編程語言。另外他在業 余時間編寫一些如本書這樣的教材和其他軟件,以及編寫他的網上日記。他的其他愛好有咖啡、 Robert Ludlum的小說、遠足和政治等。 如果你有興趣了解他的更多故事,可以在www.swaroopch.info上查看他的網上日記。 上一頁 上一級 下一頁 后記 首頁 關于譯者 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apbs02.html2010-10-3 18:11:45 簡明 Python 教程 / 關于本書 / 關于譯者 簡明 Python 教程 附錄B 關于本書 上一頁 關于譯者 下一頁 關于譯者 沈潔元 目前是上海交通大學無線通信研究所的一名碩士研究生。他現在的研究領域主要在多載波 CDMA系統的同步、信道估計、多用戶檢測等方面。Python語言(和Numeric庫)是他目前在進 行仿真和其他科研工作時使用的主要編程語言。在業余時間,他樂衷于各種FLOSS,如FreeBSD操 作系統、PyGTK等等。電影、F1賽車和網球也是他的興趣愛好。 上一頁 上一級 下一頁 關于作者 首頁 關于簡體中文譯本 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apbs03.html2010-10-3 18:11:48 簡明 Python 教程 / 關于本書 / 關于簡體中文譯本 簡明 Python 教程 附錄B 關于本書 上一頁 關于簡體中文譯本 下一頁 關于簡體中文譯本 我在半年多前開始學習使用Python編程語言。正如Swaroop在本書中所說的那樣,它很快就成 為“我最喜歡的編程語言”。目前我的几乎所有編程工作都使用Python。從我的切身體會來說, Python最大的特點就是易懂、易用、高效率。我相信,如果你已經學完了本書,并且嘗試著編寫 了一些程序后,你一定會有相同的感受。 Swaroop C. H.的這本書是我學習Python時的第一本教材。它簡單明晰,可以在最短的時間內把你 領進Python的世界。它不是很長,但是覆蓋了几乎所有重要的Python知識。在第一次讀本書的時 候,我就深切的感到這是給Python初學者的一本極佳教材,應該是每一位Python初學者的第一本 教材。 我利用業余時間翻譯了這本教材的簡體中文譯本。一方面是為了感謝Swaroop給我們帶來了那麼 好的一本教材,同時也是為了把本書介紹給更多的中國讀者,希望讓Python在中國更加普及。如 果讀了本書之后,你開始將Python應用于你的工作學習,這將是我和Swaroop以及其他Python用戶 的榮幸。如果你在學習和使用Python的過程中,遇到任何問題,你一定要試試使用Python的郵件 列表資源。你一定會得到世界各地的Python高手的熱情幫助。 本書的英文原名為《A Byte of Python》。經過與Swaroop的探討,在翻譯時,我把書名定為《簡 明 Python 教程》,以充分體現本書區別于其他Python教材的鮮明特色。在翻譯這本簡體中文譯本 時,我力求准確清晰。在原書中個別不甚清晰的地方,都與作者進行討論后再行翻譯。另外,在 這本簡體中文譯本中,我還為書中所有的程序例子配上了源代碼,并且在書后附上了中英對照的 朮語表,以便讀者以后繼續學習其他Python英文資料。 本譯本作為原書的派生作品,依照創作公用約定(署名-非派生作品-非商業用途)發布。簡單地 說,你只要署上我的名字,就可以免費復制、分發和展示本譯本。未得到我的允許,你禁止把本 譯本用于商業目的,也不能再在本譯本的基礎上修改、派生新的作品。 如果你對本書和譯本有任何批評和建議,十分歡迎你與我聯系:orion_val@163.com。 上一頁 上一級 下一頁 關于譯者 首頁 附錄C 修訂記錄 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apbs04.html2010-10-3 18:11:50 簡明 Python 教程 / 修訂記錄 / 時間表 簡明 Python 教程 附錄C 修訂記錄 上一頁 時間表 下一頁 附錄C 修訂記錄 目錄表 時間表 朮語表 時間表 本文檔在2005年1月13日4點02分生成。 修訂記錄 1.20版 2005年1月13日 使用FC3上的Quanta+的完全重寫。做了許多修正和更新。添加了許多新的例子。重寫了我的 DocBook設置。 1.15版 2004年3月28日 少量修訂。 1.12版 2004年3月16日 添加修正了一些內容。 1.10版 2004年3月9日 感謝我的熱情讀者的幫助,我對更多的筆誤做了修改。 1.00版 2004年3月8日 在從讀者處獲得了大量反饋和建議之后,我對本書的內容做了重要的修訂,并且改正了一些筆 誤。 0.99版 2004年2月22日 增加了模塊一章。增加了對可變數目函數參數的詳細介紹。 0.98版 2004年2月16日 編寫了一個Python腳本和CSS樣式表來改善XHTML的輸出效果。其中包括一個功能還很拙劣的 詞匯分析器,用來自動地為程序做類似于VIM地語法加亮。 0.97版 2004年2月13日 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apc.html(第 1/2 頁)2010-10-3 18:11:53 簡明 Python 教程 / 修訂記錄 / 時間表 (再次)使用DocBook XML完全重寫。本書改進了許多——更加有條理和易讀。 0.93版 2004年1月25日 增加了關于IDLE的介紹以及更多Windows□相關的話題。 0.92版 2004年1月5日 修改了几個例子。 0.91版 2003年12月30日 修正了排版錯誤。改進了許多章節的內容。 0.90版 2003年12月18日 增加了2章。使用OpenOffice格式修訂。 0.60版 2003年11月21日 完全地重寫和擴展。 0.20版 2003年11月20日 修改了一些排版錯誤和其他錯誤。 0.15版 2003年11月20日 改用DocBook XML。 0.10版 2003年11月14日 最初使用KWord編寫的草稿。 上一頁 上一級 下一頁 關于簡體中文譯本 首頁 朮語表 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apc.html(第 2/2 頁)2010-10-3 18:11:53 簡明 Python 教程 / 修訂記錄 / 朮語表 簡明 Python 教程 附錄C 修訂記錄 上一頁 朮語表 朮語表 argument 實參 attribute 屬性 base class 基本類 block 塊 character 字符 class 類 comment 注釋 complex number 復數 derived class 導出類 dictionary 字典 escape sequence 轉義符 exception 異常 expression 表達式 field 域 float 浮點數 function 函數 identifier 標識符 indentation 縮進 indexing 索引 instance 實例 integer 整數 list 列表 list comprehension 列表綜合 literal constant 字面意義上的常量 logical line 邏輯行 long integer 長整數 method 方法 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apcs02.html(第 1/2 頁)2010-10-3 18:11:56 簡明 Python 教程 / 修訂記錄 / 朮語表 module 模塊 namespace 名稱空間 object 對象 operand 操作數 operator 運算符 parameter 形參 pickle 儲存器 physical line 物理行 sequence 序列 shebang line 組織行 slicing 切片 statement 語句 string 字符串 subclass 子類 superclass 超類 tuple 元組 type 類型 variable 變量 上一頁 上一級 時間表 首頁 http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/apcs02.html(第 2/2 頁)2010-10-3 18:11:56 Creative Commons Deed:創作共用約定 創作共用(Creative Commons) 署名 · 禁止派生 · 非商業用途 1.0 你可以免費: ● 拷貝、分發、呈現和表演當前作品 但是必須基于以下條款: 署名。你必須明確標明作者的名字。. 非商業用途。 你不可將當前作品用于商業目的。 禁止派生。 你不可更改、轉變或者基于此作品重新構造為新作品。 ● 對于任何二次使用或分發,你必須讓其他人明確當前作品的授權條款 ● 在得到作者的明確允許下,這里的某些條款可以放棄   此約定是法律文本 (完整的協議)的簡單易讀概要 http://www.creativecommons.cn/licenses/by-nd-nc/1.0/(第 1/2 頁)2010-10-3 18:13:33 Creative Commons Deed:創作共用約定 這里的內容不是協議本身,只是一份簡單的參考說明,幫助你理解完整的法律文本(完 整的協議)。這是一份普通人可以理解的主要條款表達方式。可以認為是一份法律文本 的用戶友好界面。這里的約定本身并沒有法律意義,內容不會出現在真正的許可協議 中。 “創作共用”組織不是一家法律事務所,不對外提供法律服務。分發、呈現或者鏈接到這 個共用約定不代表建立”律師—客戶”這樣的關系。 了解如何使用本許可協議分發你的作品 http://www.creativecommons.cn/licenses/by-nd-nc/1.0/(第 2/2 頁)2010-10-3 18:13:33